<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Moro-yong.log</title>
        <link>https://velog.io/</link>
        <description>즐거운 개발을 위해~</description>
        <lastBuildDate>Tue, 24 May 2022 08:32:45 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>Moro-yong.log</title>
            <url>https://images.velog.io/images/sad_wf/profile/c3515e9f-5c54-4a87-a6ed-9bc2e905039a/스크린샷 2022-03-19 오후 4.45.46.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. Moro-yong.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sad_wf" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[프로그래머스] 문자열 p와 y의 개수]]></title>
            <link>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AC%B8%EC%9E%90%EC%97%B4-p%EC%99%80-y%EC%9D%98-%EA%B0%9C%EC%88%98</link>
            <guid>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AC%B8%EC%9E%90%EC%97%B4-p%EC%99%80-y%EC%9D%98-%EA%B0%9C%EC%88%98</guid>
            <pubDate>Tue, 24 May 2022 08:32:45 GMT</pubDate>
            <description><![CDATA[<blockquote>

<p>  <img src="https://velog.velcdn.com/images/sad_wf/post/f1703dcd-84eb-4a3d-9cbd-1b2903c3d2a7/image.png" alt=""></p>
<p>[문제 자세히 보기] (<a href="https://programmers.co.kr/learn/courses/30/lessons/12916">https://programmers.co.kr/learn/courses/30/lessons/12916</a>)</p>
</blockquote>
<br/><br/>

<p><strong>[나의 풀이]</strong></p>
<pre><code class="language-js">function solution(s){
    let upperCase = s.toUpperCase()
    let p = []
    let y = []

    for (let i=0; i &lt; upperCase.length; i++) {
      if ( upperCase[i] === &quot;P&quot;) p.push(s[i])
      else if ( upperCase[i] === &quot;Y&quot;) y.push(s[i])
    }

      if (p.length === y.length) return true
    else return false
}</code></pre>
<p>변수 <code>upperCase</code>에 주어진 s를 모두 대문자로 변경하여 저장하였다.
그후 for문을 돌면서 대문자 <code>&quot;P&quot;</code>와 <code>&quot;Y&quot;</code>랑 일치하는 문자를 변수<code>p</code> 와 <code>y</code>에 저장하고 두 변수의 크기를 비교하여 참, 거짓을 구분하였다.</p>
<p><br/><br/>
<strong>생각하기</strong>
작성한 코드를 보면 p와 y 변수를 배열로 활용하였는데 내가 알고 있는 것이 맞다면 배열이나 객체의 경우 number나 string 등에 비해 메모리를 더 많이 사용하는 것으로 알고 있다.</p>
<p>그렇기 때문에 메모리를 적게 사용하는 방법을 생각해 봤는데 아래처럼 number를 사용하면 조금은 더 좋은 코드가 될 것 같다.</p>
<pre><code class="language-js">let p = 0
let y = 0

for (let i=0; i &lt; upperCase.length; i++) {
  if ( upperCase[i] === &quot;P&quot;) p++
  else if ( upperCase[i] === &quot;Y&quot;) y++
}

if (p === y) return true
else return false</code></pre>
<p><br/><br/>
<strong>다른 사람들의 풀이</strong></p>
<p><strong>생각하기</strong>에서 카운트를 사용하여 코드를 작성하였는데 다른 사람들의 풀이를 찾아보면서 이 코드도 더 간단하게 작성할 수 있는 방법이 있었다.</p>
<pre><code class="language-js">function solution(s){
    let str= s.toLowerCase();
    let count = 0
    for(let i = 0; i &lt;s.length; i++){
        if(str[i]===&quot;p&quot;) count++;
        else if(str[i]=== &quot;y&quot;) count--
    }
    return count === 0 ? true : false
}</code></pre>
<p>내가 작성했던 코드는 p와 y의 카운트를 따로 변수에 저장하여 비교하는 코드였는데 위의 코드는 p와 동일한 개수만큼 카운트를 올리고 y와 동일한 개수만큼 카운트를 줄여서 결과값이 0이라면 true를 아니라면 false를 반환하도록 하는 코드였다.</p>
<p>변수를 하나 줄이기 때문에 당연히 메모리는 더 효율적으로 관리 될 것이고 마지막의 참 거짓을 판한하는 코드도 삼항연사자를 사용하여 보기 좋게 작성하였다.</p>
<hr>
<p>위의 것은 그래도 내가 작성했던 코드와 비슷한 방식의 풀이인데 다른 메소드를 사용하여 매우 짧게 코드를 작성하는 방법도 있었다.</p>
<pre><code class="language-js">function numPY(s){
    return s.toUpperCase().split(&quot;P&quot;).length === s.toUpperCase().split(&quot;Y&quot;).length;
}</code></pre>
<pre><code class="language-js">function numPY(s) {
  return s.match(/p/ig).length == s.match(/y/ig).length;
}</code></pre>
<p>두 코드를 보고 정말 많이 공부하고 생각을 조금 더 해봐야겠다는 생각이 든다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 문자열 내 마음대로 정렬하기]]></title>
            <link>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%82%B4-%EB%A7%88%EC%9D%8C%EB%8C%80%EB%A1%9C-%EC%A0%95%EB%A0%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%82%B4-%EB%A7%88%EC%9D%8C%EB%8C%80%EB%A1%9C-%EC%A0%95%EB%A0%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 23 May 2022 17:40:23 GMT</pubDate>
            <description><![CDATA[<blockquote>

<p>  <img src="https://velog.velcdn.com/images/sad_wf/post/33759a51-cf6e-4ba4-af57-4cf16c2b614b/image.png" alt=""></p>
<p>[문제 자세히 보기] (<a href="https://programmers.co.kr/learn/courses/30/lessons/12915">https://programmers.co.kr/learn/courses/30/lessons/12915</a>)</p>
</blockquote>
<br/><br/>

<p><strong>[나의 풀이]</strong></p>
<pre><code class="language-js">function solution(strings, n) {
    let arr = strings.sort((a, b) =&gt; {
        if (a[n] &gt; b[n]) return 1
        else if (a[n] &lt; b[n]) return -1
        else {
            if (a &gt; b) return 1
            else return -1
        }
    })

  return arr
}</code></pre>
<p>이번 문제도 결국 정렬문제이기에 <code>sort()</code> 메소드가 가장 먼저 생각나서 해당 메소드를 사용했다 다만 여러가지 조건이 있다보니 <code>if</code>, <code>else if</code>를 사용하여 조건에 맞게 정렬할 수 있도록 하였다.</p>
<pre><code class="language-js">        if (a[n] &gt; b[n]) return 1
        else if (a[n] &lt; b[n]) return -1
}</code></pre>
<p>위의 두 조건에서는 a와 b로 주어지는 요소의 <code>n번째</code> index를 비교하여 a의 n번째가 크다면 <code>1을 리턴</code> 반대로 작다면 <code>-1을 리턴</code></p>
<pre><code class="language-js">        else {
            if (a &gt; b) return 1
            else return -1
        }</code></pre>
<p>마지막으로 n번째의 요소가 동일하다면 해당 요소의 앞 요소를 비교하여 정렬하도록 하였다.</p>
<p>이렇게 작성하고 보니 뭔가 코드가 보기 애매한 느낌이라 <code>if</code>를 여러개 사용하였는데 코드를 보기에는 아래의 코드가 더 읽기 쉬운거 같다.</p>
<pre><code class="language-js">function solution(strings, n) {
  let arr = strings.sort((a, b) =&gt; {
    if (a[n] &gt; b[n]) return 1;
    if (a[n] &lt; b[n]) return -1;
    if (a[n] === b[n]) {
      if (a &gt; b) {
        return 1
      } else return -1
    }
  })

  return arr
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 정수 제곱근 판별]]></title>
            <link>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%A0%95%EC%88%98-%EC%A0%9C%EA%B3%B1%EA%B7%BC-%ED%8C%90%EB%B3%84</link>
            <guid>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%A0%95%EC%88%98-%EC%A0%9C%EA%B3%B1%EA%B7%BC-%ED%8C%90%EB%B3%84</guid>
            <pubDate>Thu, 19 May 2022 09:47:05 GMT</pubDate>
            <description><![CDATA[<blockquote>

<p>  <img src="https://velog.velcdn.com/images/sad_wf/post/6b42ff22-17ad-4eec-8c00-a2ca3aa8a293/image.png" alt=""></p>
<p>[문제 자세히 보기] (<a href="https://programmers.co.kr/learn/courses/30/lessons/12948">https://programmers.co.kr/learn/courses/30/lessons/12948</a>)</p>
</blockquote>
<br/><br/>

<p><strong>[나의 풀이]</strong></p>
<pre><code class="language-js">function solution(n) {
  let a = 0
  for (let i=0; i**2 &lt;= n; i++) {
    if (i**2 === n) {
      a = (i+1)**2
    } else {
      a = -1
    }
  }

  return a
}</code></pre>
<p>제곱이란 것이 주어진 숫자와 동일한 값으로 곱해진 것이기에 <code>for문</code>을 사용하여 반복하도록 하였다. 다만 <code>for문</code>의 반복 조건을 <code>i**2 &lt;= n</code>으로 주어 i가 제곱되었을 때 n과 같다면 반복을 멈추도록 하였다.</p>
<p>그 후는 <code>if</code>의 조건에 <code>i**2 === n</code> i의 제곱이 n과 같다면 i+1의 제곱을 하도록 작성하였다.</p>
<p>마지막으로 예외처리 되는 조건 <code>n이 양의 정수 x의 제곱이 아니라면 -1을 리턴</code>의 경우 처음 <code>if</code>에서 만약 <code>n</code>이 3으로 주어졌을 때</p>
<pre><code class="language-js">1*1 === n    // false
2*2 === n    // false
3*3 === n    // false</code></pre>
<p>위와 같이 조건에 해당하지 않아 두번째 <code>else</code>의 <code>a = -1</code>로 결과가 나오게 된다.</p>
<p>이렇게 풀고 제출해보니 아래 이미지처럼 코드의 속도가 오래걸리는 부분들이 있었다.
<img src="https://velog.velcdn.com/images/sad_wf/post/b275d6d2-1a22-41eb-9024-a19f21dbc8f0/image.png" alt="">
 테스트2, 테스트4, 테스트9 등이 그렇고 반대로 0.08ms, 0.05ms 등의 비교적 빠른 속도의 테스트도 있었는데 n으로 주어지는 숫자가 커질수록 for문이 오랫동안 돌기 때문에 그런거 같다.</p>
<p>이렇게 주어지는 n의 수가 커졌을 때도 코드가 빠르게 동작하도록 더 효율적인 코드를 고민 하도록 하자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 정수 내림차순으로 배치하기]]></title>
            <link>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%A0%95%EC%88%98-%EB%82%B4%EB%A6%BC%EC%B0%A8%EC%88%9C%EC%9C%BC%EB%A1%9C-%EB%B0%B0%EC%B9%98%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%A0%95%EC%88%98-%EB%82%B4%EB%A6%BC%EC%B0%A8%EC%88%9C%EC%9C%BC%EB%A1%9C-%EB%B0%B0%EC%B9%98%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 18 May 2022 15:34:39 GMT</pubDate>
            <description><![CDATA[<blockquote>

<p>  <img src="https://velog.velcdn.com/images/sad_wf/post/4a0d2a88-c506-47d2-886c-d5d1946188ab/image.png" alt=""></p>
<p>[문제 자세히 보기] (<a href="https://programmers.co.kr/learn/courses/30/lessons/12933">https://programmers.co.kr/learn/courses/30/lessons/12933</a>)</p>
</blockquote>
<br/><br/>

<p><strong>[나의 풀이]</strong></p>
<pre><code class="language-js">function solution(n) {
    let answer = String(n).split(&quot;&quot;).sort((a, b) =&gt; b - a).join(&quot;&quot;);

    return Number(answer)
}</code></pre>
<p>문제처럼 내림차순, 오름차순 등의 정렬이 필요할 때 <code>sort()</code>를 사용할 수 있다. <code>sort()</code> 메소드는 <code>유니코드 포인트</code>를 따르는데 아래의 표와 같다.
<img src="https://velog.velcdn.com/images/sad_wf/post/96cab41d-e150-4da3-9538-5954d5f9b63a/image.png" alt="">
표를 보면 대문자 A =&gt; U+0051 이런식으로 각 문자에 해당하는 포인트가 정해져 있고 이것을 기준으로 정렬해준다.</p>
<p>그렇기에 인수로 전해지는 <code>n</code>은 숫자와 문자 어떤것이 되더라도 정렬이 가능해진다.</p>
<p><code>n</code>으로 전달받은 <code>number</code>를 문자로 변경하고 <code>split</code>으로 각 문자를 분리해주었다. 
즉, 분리된 문자는 <code>n=118372</code>라는 숫자이기에 <code>n=&quot;118372&quot;</code>문자가 된 후 <code>[&quot;1&quot;, &quot;1&quot;, &quot;8&quot;, &quot;3&quot;, &quot;7&quot;, &quot;2&quot;]</code>가 된다.</p>
<p>이것을 <code>sort()</code>로 정렬하고 <code>join()</code>으로 다시 합하여 <code>return</code> 할 때 숫자로 변경하여 리턴하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 최소직사각형]]></title>
            <link>https://velog.io/@sad_wf/Temp-Title</link>
            <guid>https://velog.io/@sad_wf/Temp-Title</guid>
            <pubDate>Tue, 03 May 2022 08:32:08 GMT</pubDate>
            <description><![CDATA[<blockquote>

<p>  <img src="https://velog.velcdn.com/images/sad_wf/post/79fba6e7-6df3-45a4-85a4-8b28eccfdb7e/image.png" alt=""></p>
<p>[문제 자세히 보기] (<a href="https://programmers.co.kr/learn/courses/30/lessons/86491">https://programmers.co.kr/learn/courses/30/lessons/86491</a>)</p>
</blockquote>
<br/><br/>

<p>문제를 보면 명함을 돌려서 수납할 수 있다는 말이 있고 모든 명함을 수납할 수 있는 가장 작은 사이즈의 지갑을 만드려고 한다.</p>
<p>가로의 최대 길이와 세로의 최대 길이를 구해야하는데 최대 길이를 구할 때 회전했을 경우 즉 [a, b] 명함의 가로세로 길이, a와 b의 순서가 바뀌어도 된다는 것으로 이해했다. </p>
<p>sort()를 사용하여 각각의 배열 안의 숫자를 오름차순으로 변경하고 for문을 통해 돌고있는 i로 각각의 명함 크기가 bestSize의 [0]과 [1]보다 크면 bestSize에 저장하여 각각의 최대 사이즈를 구하고 곱하는 방식으로 해결하였다.
<br/></p>
<p><strong>[나의 풀이]</strong></p>
<pre><code class="language-js">function solution(sizes) {
  let bestSize = [0,0]

  for (let i =0; sizes.length &gt; i; i++) {
    let [a,b] = sizes[i].sort((a,b) =&gt; a-b)
    if (a &gt; bestSize[0]) {
      bestSize[0] = a
    }
    if (b &gt; bestSize[1]) {
      bestSize[1] = b
    }
  }

  return bestSize[0]*bestSize[1]
}</code></pre>
<p><br/><br/></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[sort()]]></title>
            <link>https://velog.io/@sad_wf/sort</link>
            <guid>https://velog.io/@sad_wf/sort</guid>
            <pubDate>Tue, 03 May 2022 08:18:26 GMT</pubDate>
            <description><![CDATA[<blockquote>
MDN<br/>
sort() 메서드는 배열의 요소를 적절한 위치에 정렬한 후 그 배열을 반환합니다. 정렬은 stable sort가 아닐 수 있습니다. 기본 정렬 순서는 문자열의 유니코드 코드 포인트를 따릅니다.

</blockquote>

<ul>
<li>배열 안의 원소를 정렬하는 함수이다.</li>
<li>인수를 지정하지 않으면 유니코드 포인트를 따라 정렬된다.</li>
<li>인수를 지정하여 정렬방법을 변경할 수 있다.
<br/><br/></li>
</ul>
<pre><code class="language-js">let numbers = [4, 16, 3, 53, 1, 0];

오름차순 정렬
numbers.sort((a, b) =&gt; a-b) // [0, 1, 3, 4, 16, 53]

내림차순 정렬
numbers.sort((a, b) =&gt; b-a) // [53, 16, 4, 3, 1, 0]</code></pre>
<br/>

<p>위의 코드에서는 화살표 함수를 사용하였는데 아래와 같이 사용할 수도 있다.
<br/></p>
<pre><code class="language-js">let numbers = [4, 16, 3, 53, 1, 0];

오름차순 정렬
numbers.sort(function(a, b) {
    return a-b
}) 
// [0, 1, 3, 4, 16, 53]</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 핸드폰 번호 가리기]]></title>
            <link>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%95%B8%EB%93%9C%ED%8F%B0-%EB%B2%88%ED%98%B8-%EA%B0%80%EB%A6%AC%EA%B8%B0</link>
            <guid>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%95%B8%EB%93%9C%ED%8F%B0-%EB%B2%88%ED%98%B8-%EA%B0%80%EB%A6%AC%EA%B8%B0</guid>
            <pubDate>Tue, 26 Apr 2022 10:35:26 GMT</pubDate>
            <description><![CDATA[<blockquote>

<p>  <img src="https://velog.velcdn.com/images/sad_wf/post/6b42ff22-17ad-4eec-8c00-a2ca3aa8a293/image.png" alt=""></p>
<p>[문제 자세히 보기] (<a href="https://programmers.co.kr/learn/courses/30/lessons/12948">https://programmers.co.kr/learn/courses/30/lessons/12948</a>)</p>
</blockquote>
<br/><br/>

<p><strong>[나의 풀이]</strong></p>
<pre><code class="language-js">function solution(phone_number) {
  let answer = &#39;&#39;;
  const count = phone_number.length

  for (let i=0; count &gt; i; i++) {
    if (i &lt;= count -5) {
      answer += &quot;*&quot;
    }
    if (i &gt; count -5) {
      answer += phone_number[i]
    }
  }
  return answer;
}</code></pre>
<p>문제를 읽고 쉽게 생각해보면 결국 맨 뒤의 4개의 숫자만 남기고 앞의 모든 숫자를 *로 변경하면 된다고 생각했다.</p>
<p>phone_number를 받았을 때 for문을 사용하여 순회하고
if를 사용하여 index가 -5보다 작거나 같으면 *을 더하여 answer에 저장,
-5보다 크면 해당 index의 값을 그대로 더하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[jQuery를 사용한 프로젝트?]]></title>
            <link>https://velog.io/@sad_wf/jQuery%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@sad_wf/jQuery%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Sun, 10 Apr 2022 09:15:44 GMT</pubDate>
            <description><![CDATA[<p>시작하기 전에 jQuery는 이제 거이 사용하지 않는 라이브러리다. 그럼에도 프로젝트를 진행하면서 jQuery를 사용해봤는데 이유는 리액트를 사용하여 웹을 만들면서 모르는 것을 검색하다보면 간간히 jQuery를 사용한 코드가 나오기도 하고 혹여나 jQuery를 사용했던 프로젝트를 건드려야 할 경우가 생기지 않을까?하는 생각에 깊게는 아니더라도 알고 있다면 모르는 것보다는 좋지 않을까 생각하여 사용해봤다.<br/><br/></p>
<h2 id="jquery">jQuery?</h2>
<p>몇 년 전까지는 jQuery에 대한 의존도가 다소 높았기에 jQuery가 많이 사용되었지만 2015년을 기점으로 그 의존도가 점점 내려가면서 현재는 거이 사용하지 않는 기술이 되었다.</p>
<p>그전에 jQuery를 사용했던 이유는 아래와 같은 이유가 있다고 한다.</p>
<ul>
<li>웹페이지 상에서 엘리먼트(Element)를 쉽게 찾고 조작할 수 있다.</li>
<li>대부분의 웹브라우저에 대응되는 호환성</li>
<li>네트워크, 애니메이션 등 다양한 기능을 제공한다.</li>
<li>짧고 유지관리가 용이한 코드 작성을 지원한다.
<br/><br/></li>
</ul>
<h3 id="jquery를-점점-사용하지-않는-이유">jQuery를 점점 사용하지 않는 이유</h3>
<p><strong>웹 브라우저 환경의 변화</strong></p>
<p>jQuery를 사용했던 이유는 여러가지가 있겠지만 당연하게도 편리하고 다양한 기능을 제공하기 때문이다. 그런데 예전에는 internet explorer 브라우저의 점유율이 너무나 높았던 시기가 있고 해당 브라우저에서 생산성과 가독성을 높인 코드를 작성하기 위해서 jQuery가 필요했다. 그러나 크롬 브라우저의 등장과 함께 모바일 브라우저 등 다양한 브러우저가 등장하면서 우수한 렌더링 엔진과 빠른 업데이트 등으로 브라우저 점유율에 변동이 생겼고 더 이상 jQuery를 사용하지 않더라도 브라우저 자체에서 편리한 기능을 제공하게 되면서 필요성이 감소하였다.
<br/></p>
<h3 id="그래서-jquery를-배워야-할까">그래서 jQuery를 배워야 할까?</h3>
<p>솔직히 말해서 jQuery를 점점 사용하지 않는다고 하더라도 아직까지 종종 모습을 보이는 것을 보면 한번 쯤은 관련 문서를 읽어봐도 괜찮지 않을까 싶다. 
그렇다고 jQuery에 대해서 깊게 공부한다기 보다는 jQuery관련 내용이 나왔을 때 해당 코드가 무엇을 의미하는지 정도는 알고 있다면 도움이 될 것이라고 생각한다.
즉 중요도는 떨어지더라도 여유가 된다면 공부해보자? 정도로 볼 수 있을거 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[context & redux]]></title>
            <link>https://velog.io/@sad_wf/context-useContext</link>
            <guid>https://velog.io/@sad_wf/context-useContext</guid>
            <pubDate>Sat, 09 Apr 2022 07:56:27 GMT</pubDate>
            <description><![CDATA[<h2 id="component-tree-구조">component tree 구조</h2>
<p><img src="https://velog.velcdn.com/images/sad_wf/post/b0dc579c-3f22-410a-9255-74d398f58e69/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-04-09%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%202.55.02.png" alt="">[이미지 출처] (<a href="https://www.youtube.com/watch?v=LwvXVEHS638">https://www.youtube.com/watch?v=LwvXVEHS638</a>)</p>
<p>위의 이미지는 우리가 리액트로 웹을 만들 때 컴포넌트들의 트리구조를 나타내고 있는 이미지다. 
이러한 트리구조를 가진 리액트에서 전역(지역) 데이터를 상위 컴포넌트에서 하위 컴포넌트로 전달해 주려면 prop를 통해서 위에서 아래로 계속해서 내려줘야 하는데 컴포넌트의 구조가 단순하고 적다면 크게 문제가 되지 않지만 이 구조가 복잡해지고 많아진다면 문제가 발생한다. </p>
<ol>
<li>prop이 여러 컴포넌트에서 사용되면서 의도치 않은 값이 될 수 있다.</li>
<li>컴포넌트의 뎁스가 깊어질수록 prop를 계속해서 사용해야 하기에 개발자는 에러가 생겼을 때 위치를 특정하기가 힘들어진다.</li>
<li>prop이 변경될 경우 페이지는 리렌더링이 이루어지는데 아래의 컴포넌트에서 변화가 생기면 상위 컴포넌트도 불필요한 리렌더링이 이루어진다. </li>
</ol>
<p>그렇기 때문에 이를 해결하기 위한것이 context로 app 컴포넌트에서 데이터를 가지고 있다면 필요한 곳에서만 해당 데이터를 가져다 사용할 수 있게 해주어서 위의 문제점들을 해결한다.
<br/><br/></p>
<hr>
<br/>


<h2 id="context와-redux">context와 redux</h2>
<p>두 가지의 도구는 얼뜻 보면 동일한 기능을 하는 것 같지만 사용의 목적이 다르다. </p>
<h3 id="context-특징">context 특징</h3>
<ul>
<li><p><strong>다양한 컴포넌트에 전역적인 데이터를 전달하기 위해 사용</strong>하는 도구이며 &quot;<strong>상태관리를 위한 도구는 아니다.</strong>&quot;
<code>상태관리란 시간이 지남에 따라 상태가 변경되는 방식을 말하며 리액트에서 상태를 관리하는 도구는 useState와 useReducer를 통해서 이루어진다.</code></p>
</li>
<li><p>리액트의 내장 기능이다.</p>
</li>
</ul>
<h4 id="그렇다면-언제-사용하는가">그렇다면 언제 사용하는가?</h4>
<p><strong>props drilling</strong>을 피할 때 즉 context.provider 내부에서 상태 변경이 거이 없을 때 하위 컴포넌트에 전달하는 용도로 쓰는데 사용하기 좋다.
<code>props drilling은 props를 하위 컴포넌트로 전달하는 용도로&quot;만&quot; 쓰이는 컴포넌트들을 거치면서 react component트리의 한 컴포넌트에서 다른 곳으로 데이터를 전달하는 과정을 말한다.</code></p>
<h4 id="장점">장점</h4>
<ul>
<li>prop을 사용하여 데이터를 전달하지 않아도 되기에 코드가 짧아진다.</li>
</ul>
<h4 id="단점">단점</h4>
<ul>
<li>context를 사용하려면 Provider를 사용해야 하는데 이를 분리할 수 없기에 재사용성이 떨어진다.
<br/><br/><br/></li>
</ul>
<h3 id="redux-특징">redux 특징</h3>
<p>애플리케이션 전체의 상태 중앙 저장소 역할을 하며 애플리케이션의 상태를 예측 가능한 방식으로 업데이트 하기 위해서 사용하는 라이브러리다.</p>
<p>여러 위치에 많은 양의 상태 값이 존재 할 때</p>
<ul>
<li>업데이트 로직이 복잡 할 때</li>
<li>거대한 코드 베이스를 여러 사람이 작업 할 때</li>
<li>상태 변경 시각화가 필요 할 때</li>
<li>사이드이펙트, 메모이제이션, 데이터 직렬화등 관리를 위해 더 강력한 기능이 필요 할 때</li>
</ul>
<h4 id="장점-1">장점</h4>
<ul>
<li>상태의 중앙화
  웹사이트의 상태를 한 곳에서 관리할 수 있기 때문에 store prop을 사용하지 않고 에러를 찾아내기 쉽다.</li>
<li>단방향 모델링
  리덕스는 action은 dispatch를 거쳐서 데이터가 변경되고 store를 통해 전달받아 웹에 보여준다. 이 단방향 모델링으로 디버깅이 쉽다.</li>
<li>읽기전용 취급
  리덕스의 상태는 읽기 전용으로 취급한다. 실제로 읽기 전용으로 만드는 것은 아니기에 주의할 필요가 있으나 이로인해 이전 상태로 돌아가기 위해서 이전 상태를 현재 상태에 덮어쓰기만 하면 된다.</li>
</ul>
<h4 id="단점-1">단점</h4>
<ul>
<li>익숙해 지기전에는 리덕스를 쓰기 위해서 reducer, store, dispatch, action 등 작성해야 하는 코드가 많고 복잡하기도 하다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 숫자 문자열과 영단어]]></title>
            <link>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%88%AB%EC%9E%90-%EB%AC%B8%EC%9E%90%EC%97%B4%EA%B3%BC-%EC%98%81%EB%8B%A8%EC%96%B4</link>
            <guid>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%88%AB%EC%9E%90-%EB%AC%B8%EC%9E%90%EC%97%B4%EA%B3%BC-%EC%98%81%EB%8B%A8%EC%96%B4</guid>
            <pubDate>Fri, 01 Apr 2022 03:19:44 GMT</pubDate>
            <description><![CDATA[<blockquote>
  네오와 프로도가 숫자놀이를 하고 있습니다. 네오가 프로도에게 숫자를 건넬 때 일부 자릿수를 영단어로 바꾼 카드를 건네주면 프로도는 원래 숫자를 찾는 게임입니다.

<p>다음은 숫자의 일부 자릿수를 영단어로 바꾸는 예시입니다.</p>
<p>1478 → &quot;one4seveneight&quot;
234567 → &quot;23four5six7&quot;
10203 → &quot;1zerotwozero3&quot;
이렇게 숫자의 일부 자릿수가 영단어로 바뀌어졌거나, 혹은 바뀌지 않고 그대로인 문자열 s가 매개변수로 주어집니다. s가 의미하는 원래 숫자를 return 하도록 solution 함수를 완성해주세요.</p>
<p>참고로 각 숫자에 대응되는 영단어는 다음 표와 같습니다.
<img src="https://media.vlpt.us/images/sad_wf/post/5200295f-5eac-439d-99eb-022990da04d4/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-04-01%20%E1%84%8B%E1%85%A9%E1%84%8C%E1%85%A5%E1%86%AB%2011.25.08.png" alt=""></p>
<p>문제 자세히 보기 : <a href="https://programmers.co.kr/learn/courses/30/lessons/81301">https://programmers.co.kr/learn/courses/30/lessons/81301</a></p>
</blockquote>
<br/><br/>

<p><strong>[나의 풀이]</strong></p>
<pre><code class="language-js">function solution(s) {
    const answer = Number(s.replace(/zero/g, 0)
    .replace(/one/g, 1)
    .replace(/two/g, 2)
    .replace(/three/g, 3)
      .replace(/four/g, 4)
      .replace(/five/g, 5)
      .replace(/six/g, 6)
      .replace(/seven/g, 7)
      .replace(/eight/g, 8)
      .replace(/nine/g, 9))

    return answer;
}</code></pre>
<p>정규식을 사용하여 문제를 풀었는데... 일단 결과는 성공적으로 작동 잘 되었다. 
다만 지금 풀이가 문제라고 생각되는게 replace를 여러번 반복했는데 이게 지금은 0<del>9까지만 고려하면 되기에 반복이 다소 적지만 저런 조건이 추가 될 때마다 replace를 반복해야하니 더 좋은 방법을 찾아보자</del></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[프로그래머스] 신규 아이디 추천]]></title>
            <link>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%8B%A0%EA%B7%9C-%EC%95%84%EC%9D%B4%EB%94%94-%EC%B6%94%EC%B2%9C</link>
            <guid>https://velog.io/@sad_wf/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%8B%A0%EA%B7%9C-%EC%95%84%EC%9D%B4%EB%94%94-%EC%B6%94%EC%B2%9C</guid>
            <pubDate>Wed, 30 Mar 2022 12:43:07 GMT</pubDate>
            <description><![CDATA[<blockquote>

<h3 id="문제-설명">문제 설명</h3>
<p>카카오에 입사한 신입 개발자 네오는 &quot;카카오계정개발팀&quot;에 배치되어, 카카오 서비스에 가입하는 유저들의 아이디를 생성하는 업무를 담당하게 되었습니다. &quot;네오&quot;에게 주어진 첫 업무는 새로 가입하는 유저들이 카카오 아이디 규칙에 맞지 않는 아이디를 입력했을 때, 입력된 아이디와 유사하면서 규칙에 맞는 아이디를 추천해주는 프로그램을 개발하는 것입니다.
다음은 카카오 아이디의 규칙입니다.</p>
<p>아이디의 길이는 3자 이상 15자 이하여야 합니다.
아이디는 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.) 문자만 사용할 수 있습니다.
단, 마침표(.)는 처음과 끝에 사용할 수 없으며 또한 연속으로 사용할 수 없습니다.
&quot;네오&quot;는 다음과 같이 7단계의 순차적인 처리 과정을 통해 신규 유저가 입력한 아이디가 카카오 아이디 규칙에 맞는 지 검사하고 규칙에 맞지 않은 경우 규칙에 맞는 새로운 아이디를 추천해 주려고 합니다.
신규 유저가 입력한 아이디가 new_id 라고 한다면,</p>
<hr>
<p><strong>1단계</strong> new_id의 모든 대문자를 대응되는 소문자로 치환합니다.
<strong>2단계</strong> new_id에서 알파벳 소문자, 숫자, 빼기(-), 밑줄(_), 마침표(.)를 제외한 모든 문자를 제거합니다.
<strong>3단계</strong> new_id에서 마침표(.)가 2번 이상 연속된 부분을 하나의 마침표(.)로 치환합니다.
<strong>4단계</strong> new_id에서 마침표(.)가 처음이나 끝에 위치한다면 제거합니다.
<strong>5단계</strong> new_id가 빈 문자열이라면, new_id에 &quot;a&quot;를 대입합니다.
<strong>6단계</strong> new_id의 길이가 16자 이상이면, new_id의 첫 15개의 문자를 제외한 나머지 문자들을 모두 제거합니다.
     만약 제거 후 마침표(.)가 new_id의 끝에 위치한다면 끝에 위치한 마침표(.) 문자를 제거합니다.
<strong>7단계</strong> new_id의 길이가 2자 이하라면, new_id의 마지막 문자를 new_id의 길이가 3이 될 때까지 반복해서 끝에 붙입니다.</p>
<p>자세한 문제는 <a href="https://programmers.co.kr/learn/courses/30/lessons/72410">https://programmers.co.kr/learn/courses/30/lessons/72410</a> 참고</p>
</blockquote>


<p><strong>[문제]</strong>
신규 유저가 입력한 아이디를 나타내는 new_id가 매개변수로 주어질 때, &quot;네오&quot;가 설계한 7단계의 처리 과정을 거친 후의 추천 아이디를 return 하도록 solution 함수를 완성해 주세요.</p>
<p><strong>[제한사항]</strong>
new_id는 길이 1 이상 1,000 이하인 문자열입니다.
new_id는 알파벳 대문자, 알파벳 소문자, 숫자, 특수문자로 구성되어 있습니다.
new_id에 나타날 수 있는 특수문자는 -_.~!@#$%^&amp;*()=+[{]}:?,&lt;&gt;/ 로 한정됩니다.
<br/><br/></p>
<hr>
<p><br/><br/></p>
<p><strong>[나의 풀이]</strong></p>
<pre><code class="language-js">function solution(new_id) {
    var answer = new_id.toLowerCase()
    .replace(/[^a-z0-9-_., &#39;&#39;]/g,&#39;&#39;)
    .replace(/[.]{2,}/g,&quot;.&quot;)
    .replace(/^[.]|[.]$/g,&quot;&quot;)

    if (answer===&#39;&#39;) {
      answer = &#39;a&#39;
    } else if (answer.length &gt;= 16) {
      answer = answer.slice(0, 15).replace(/[.]$/g,&quot;&quot;)
    } 

    while(answer.length &lt; 3) {
      answer += answer[answer.length - 1]
    }

    return answer;
}</code></pre>
<p>실행 결과는 아래와 같이 정확성 80% 성공으로 처참하게 실패...
<img src="https://images.velog.io/images/sad_wf/post/6b14f884-2480-4e64-b9e7-be7b41ddef2f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-30%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%207.31.17.png" alt=""><br/><br/></p>
<p><strong>[다시 생각해보기]</strong></p>
<p>무엇이 문제인지 생각해보면서 이거저거 건들여봤는데 두번째 조건이 틀렸었다.</p>
<pre><code class="language-js">.replace(/[^a-z0-9-_., &#39;&#39;]/g,&#39;&#39;)</code></pre>
<p>잘 보면 9-_. 다음에 ,부터 &#39;&#39;까지 작성된 것이 있는데 이건 의도하고 작성한게 아니고 정규식을 작성하면서 딴짓을 한 것인지 잘못 작성되어 있었다 ;;</p>
<pre><code class="language-js">.replace(/[^a-z0-9-_.]/g,&#39;&#39;)</code></pre>
<p>아래와 같이 고치니 문제없이 통과!
<br/><br/><br/></p>
<p><strong>[최종답 &amp; 문제풀이]</strong></p>
<pre><code class="language-js">function solution(new_id) {
    var answer = new_id.toLowerCase()
    .replace(/[^a-z0-9-_.]/g,&#39;&#39;)
    .replace(/[.]{2,}/g,&quot;.&quot;)
    .replace(/^[.]|[.]$/g,&quot;&quot;)

    if (answer===&#39;&#39;) {
      answer = &#39;a&#39;
    } else if (answer.length &gt;= 16) {
      answer = answer.slice(0, 15).replace(/[.]$/g,&quot;&quot;)
    } 

    while(answer.length &lt; 3) {
      answer += answer[answer.length - 1]
    }

    return answer;
}
</code></pre>
<p><br/><br/>
<strong>1단계</strong>
<code>toLowerCase()</code>을 사용하여 모든 문자를 소문자로 치환</p>
<p><strong>2단계</strong>
<code>.replace(/[^a-z0-9-_.]/g,&#39;&#39;)</code> .replace메서드와 정규식을 사용하여 <code>a부터 z까지</code>, <code>0부터 9까지</code>, <code>-</code>, <code>_</code>, <code>.</code> 를 제외한 문자열을 제거</p>
<p><strong>3단계</strong>
<code>.replace(/[.]{2,}/g,&quot;.&quot;)</code> 2단계를 거친 문자열에서 <code>.</code>이 2번 이상 반복되면 <code>.</code>한개로 치환</p>
<p><strong>4단계</strong>
<code>.replace(/^[.]|[.]$/g,&quot;&quot;)</code> 3단계 이후 문자열에서 처음과 끝이 <code>.</code>이면 빈 문자열(삭제)로 치환</p>
<p><strong>5~6단계</strong>
if문을 사용하여 <code>answer</code>가 <code>&#39;&#39;</code>이면 <code>&#39;a&#39;</code>로 치환 이후 else ifd에서 answer의 길이가 16이상이면 slice를 사용하여 15번째 이후 문자를 제거하고 <code>.replace(/[.]$/g,&quot;&quot;)</code>로 마지막이 <code>.</code>이면 제거</p>
<p><strong>7단계</strong></p>
<pre><code>while(answer.length &lt; 3) {
      answer += answer[answer.length - 1]
    }</code></pre><p>while문을 사용하여 조건이 3 이하일 경우 answer의 마지막 단어를 계속 추가하도록 작성</p>
<p>7단계에서 while문은 거이 사용하지 않다보니 if문을 사용하여 작성하려 했는데 작성하는 과정에서 굳이? 더 쉽게 작성하는 방법이 없을까 생각하게 되어서 while문으로 변경하게 되었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TCP의 구조]]></title>
            <link>https://velog.io/@sad_wf/TCP%EC%9D%98-%EA%B5%AC%EC%A1%B0</link>
            <guid>https://velog.io/@sad_wf/TCP%EC%9D%98-%EA%B5%AC%EC%A1%B0</guid>
            <pubDate>Mon, 28 Mar 2022 13:59:36 GMT</pubDate>
            <description><![CDATA[<h2 id="tcp-구조">TCP 구조</h2>
<p><strong>TCP 헤더</strong>
TCP통신으로 데이터를 보낼 때 <strong>헤더를 붙여서 보내는 것을 TCP 헤더라고 하며, TCP 헤더가 붙은 데이터를 세그먼트</strong>라고 한다.
이 헤더에는 출발지 포트번호(16비트)부터 목적지 포트번호(16비트)... 옵션까지 11가지의 데이터가 포함되어 있다.</p>
<h3 id="1-코드비트">1. 코드비트</h3>
<p>코드비트에는 정보의 연결 제어 정보가 기록되고 이 기록을 토대로 가상의 독점 통신로를 확보한다.
<strong>가상의 독점 통신로</strong> : TCP통신에서 정보를 전달하기 위해 사용되는 가상의 통신로. 연결의 확립 및 데이터 전송</p>
<p><strong>3-way 핸드셰이크</strong>
데이터를 보내기 전 연결 확립을 위해 패킷 요청을 세번 교환하는 과정.
코드비트 중 ACK=확인 응답, SYN=연결요청을 사용하여 패킷을 교환하는 과정을 거친다.</p>
<ol>
<li>A 컴퓨터가 B컴퓨터에 통신하기 위해서 연결 확립 요청(SYN) 전달</li>
<li>B 컴퓨터는 허가 응답을 위해 연결확립 응답(ACK) 전달, 동시에 B 컴퓨터도 데이터 전송 허가를 받기위해 A 컴퓨터에 연결 확립 요청(SYN)</li>
<li>A 컴퓨터가 받은 B 컴퓨터의 응답에 대한 응답으로 연결확립 응답(ACK) 전달</li>
</ol>
<p>위의 경우는 연결을 하기위한 과정이고 반대로 연결을 해제하기 위한 과정도 있다.
코드비트 중 ACK=확인 응답, FIN=연결 종료를 사용하고 과정은 위의 1~3과 동일하지만 SYN이 FIN으로 대체되어 있다고 생각하면 편하다.
<br/><br/></p>
<h3 id="2-일련번호-확인-응답-번호">2. 일련번호, 확인 응답 번호</h3>
<p>일련번호는 송식 측에서 수신측에 해당 데이터가 몇 번째 데이터인지를 알려주며 몇 번째 데이터를 받았는지 확인하여 수신측에 알려거나 다음 데이터를 요청하는데 사용된다.</p>
<p><strong>재전송 제어</strong>
<strong>데이터가 손상 및 유실 되었을 경우</strong> 데이터를 재전송 시켜달라고 하는데 이것을 재전송 제어라고 한다.
<br/><br/></p>
<h3 id="3-윈도우-크기">3. 윈도우 크기</h3>
<p>세그먼트를 하나 보낼 때 마다 응답을 기다리는 방식이 <strong>3-way 핸드셰이크</strong> 방식인데 이 방식의 경우 매번 응답을 기다려야해서 효율이 좋지 않다. 
그렇기에 세그먼트를 연속해서 보내고 응답을 한번에 받게 되면 효율이 높아지는데 많은 양의 세그먼트를 보낼 경우 그것을 보관하는 장소를 <strong>버퍼</strong>라고 하며 버퍼보다 양이 많아 넘칠경우 이것을 <strong>오버플로</strong>라고 한다.</p>
<p><strong>오버플로</strong>가 발생하지 않도록 버퍼의 한계 크기를 정해두는데 윈도우 크기값에 그 크기를 저장해둔다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[전송계층]]></title>
            <link>https://velog.io/@sad_wf/%EC%A0%84%EC%86%A1%EA%B3%84%EC%B8%B5</link>
            <guid>https://velog.io/@sad_wf/%EC%A0%84%EC%86%A1%EA%B3%84%EC%B8%B5</guid>
            <pubDate>Thu, 24 Mar 2022 13:45:08 GMT</pubDate>
            <description><![CDATA[<h2 id="전송계층의-역할">전송계층의 역할</h2>
<ul>
<li><p><strong>오류를 점검하는 기능</strong>
네트워크가 데이터를 전송할 때 물리계층, 데이터 링크 계층, 네트워크 계층 3개만 있으면 데이터를 보내는 것은 가능하다.
그러나 데이터가 손상되거나 유실되었을 때 문제점을 해결해주지는 못 한다.
이러한 문제를 해결해주는 계층이 전송계층으로 <strong>목적지에 신뢰할 수 있는 데이터를 전달</strong>하는 역할을 해준다.</p>
<ul>
<li>이 단계에서 데이터에 오류가 생기면 데이터를 재전송하도록 요청한다.<br/>
</li>
</ul>
</li>
<li><p><strong>전송된 데이터의 목적지가 어떤 애플리케이션인지 구분하는 기능</strong>
데이터를 전송받은 후 해당 데이터가 어떤 애플리케이션에서 사용되는 데이터인지 확인한다.
ex) A데이터가 메일 앱에서 사용되는 것인지 브라우저 앱에서 사용되는지 확인 후 알맞은 곳으로 데이터를 전송하게 해준다.</p>
</li>
</ul>
<h2 id="통신-유형">통신 유형</h2>
<p>데이터를 전달하는 통신 유형은 두 가지가 있다.</p>
<ul>
<li><p><strong>TCP(연결형 통신)</strong>
  신뢰성과 정확성을 목적으로 통신.
  데이터가 목적지까지 문제없이 전달되는지 확인하는데 이 방식은 데이터 송수신 간에 확인을 하면서 보내게 된다.</p>
  <br/>
</li>
<li><p><strong>UDP(비연결 통신)</strong>
  효율성(속도)를 목적으로 통신.
  TCP와 다른 점은 데이터를 송신할 때 수신측에 확인을 받지 않고 일방적으로 데이터를 전달한다.</p>
  <br/>

</li>
</ul>
<p><img src="https://images.velog.io/images/sad_wf/post/d1e58cf1-326c-47de-86de-f103eabc059e/OSI%20%E1%84%8C%E1%85%A5%E1%86%AB%E1%84%89%E1%85%A9%E1%86%BC%20%E1%84%80%E1%85%A8%E1%84%8E%E1%85%B3%E1%86%BC.jpg" alt="">
이미지 출처 : 모두의 네트워크_도서</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[네트워크 _ 네트워크 접속 계층]]></title>
            <link>https://velog.io/@sad_wf/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%A0%91%EC%86%8D-%EA%B3%84%EC%B8%B5</link>
            <guid>https://velog.io/@sad_wf/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-%EC%A0%91%EC%86%8D-%EA%B3%84%EC%B8%B5</guid>
            <pubDate>Tue, 22 Mar 2022 14:03:14 GMT</pubDate>
            <description><![CDATA[<h1 id="네트워크-접속-계층">네트워크 접속 계층</h1>
<p>TCP/IP모델을 설명할 때 OSI모델과의 차이점에 계층의 갯수가 있었다.
OSI모델의 물리 계층과 데이터 링크 계층이 TCP/IP모델에서는 네트워크 접속 계층에서 해당 역할을 대신하고 있다. 즉 네트워크 접속 계층은 두 계층을 가지고 있는 것이니 두 가지에 대해서 조금 더 자세히 알아보자.
<br/><br/></p>
<h2 id="물리-계층">물리 계층</h2>
<p>데이터를 송수신 할 때 0과 1로 이루어진 비트열의 데이터를 전기 신호로 변환해야 한다.
전기 신호의 종류에는 아날로그 신호와 디지털 신호 두가지가 있다.</p>
<p>두 신호에 대한 자세한 설명은 내용이 깊어지기에 잠시 미루고 우리가 데이터를 전송할 때는 디지털 신호를 사용한다.</p>
<p>그렇다면 어떻게 비트열 데이터를 디지털 신호로 변경할까? 컴퓨터를 조금 알고 있다면 들어보았을 랜 카드라는 것이 그 역할을 한다.
<br/><br/></p>
<h2 id="데이터-링크-계층">데이터 링크 계층</h2>
<p>데이터 링크 계층은 물리 계층에서 변환한 데이터를 송수신하는 계층이다.
조금 더 설명하면 네트워크 장비 간의 신호를 주고받는 규칙을 정하는 계층이며, 여러가지 규칙이 있지만 이더넷을 많이 사용한다.
<img src="https://images.velog.io/images/sad_wf/post/9335f157-09dd-4d4c-9f73-c082926335ca/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-03-22%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2010.20.41.png" alt=""></p>
<p>여러개의 네트워크 장비를 랜에 연결하기 위해서 사용하는 허브(또는 스위치)가 있다.
위의 이미지가 허브인데 pc1부터 pc4까지를 랜에 연결하여 서로 데이터를 주고 받을 때 pc1에서 pc3으로 데이터를 주려고 해도 실제로 데이터는 pc2~pc4까지 모두 전달하게 된다. 즉 우리가 원치 않는 장비로 데이터를 전달해주게 된다.</p>
<p>이때 데이터 링크 계층에서 규칙을 정해 데이터를 전달하더라도 목적지의 pc가 아니라면 무시하도록 해준다.
<br/><br/></p>
<h3 id="이더넷은-무엇일까">이더넷은 무엇일까?</h3>
<p>허브를 사용해서 데이터를 주고 받을 때 만약 pc1과 pc3이 동시에 다른 pc로 데이터를 전달하게 되면 두 데이터가 서로 충돌하게 된다.
이때 이러한 충돌이 일어나지 않도록 규칙을 정한 구조를 이더넷이라고 하고 이 방법을 CSMA/CD라고 한다.</p>
<h4 id="csmacd">CSMA/CD</h4>
<ul>
<li>CS는 데이터를 보내려하는 장비가 케이블에 신호가 잘 연결되어 있는지 확인하는 규칙이다.</li>
<li>MA는 케이블에 데이터가 흐르고 있지 않다면 데이터를 보내도록 하는 규칙이다.</li>
<li>CD는 충돌이 발생하고 있는지 확인하는 규칙이다.</li>
</ul>
<p>이 세가지 규칙을 통해서 pc1과 3이 동시에 데이터를 보낼 때 pc1의 데이터를 먼저 보내고 pc3은 그동안 대기하다가 pc1이 데이터를 다 보내면 pc3이 데이터를 보내도록 해서 충돌을 막아준다.
<br/><br/></p>
<h3 id="스위치">스위치</h3>
<h4 id="csmacd는-효율이-별로">CSMA/CD는 효율이 별로?</h4>
<p>CSMA/CD 방식의 경우 양방향 1차선 도로를 생각해보면 이해가 잘 될거 같다. 시골길에서 차량이 지나가는데 길은 좁은 통로 하나고 서로 차량이 마주한다면 1대의 차량이 비켜주고 다른 차량이 먼저 지나간 후 남은 차량이 지나가는데 그러면 시간이 오래 걸린다.</p>
<p>즉 효율이 매우 떨어진다.</p>
<p>그래서 지금은 CSMA/CD방식을 사용하지 않고 스위치라는 장비를 사용한다.</p>
<h4 id="mac주소">MAC주소</h4>
<p>스위치에 대해서 알기전에 MAC주소를 알아야하는데 비트열 데이터를 전기신호로 변경해주는 랜카드에는 제조할 때 정해진 주소를 할당하고 그 주소가 MAC주소이다. 이는 허브와 스위치 모두에서 사용된다</p>
<p><strong>참고</strong> : MAC주소는 <strong>물리주소</strong>라고도 불리며 세계에서 유일한 번호로 1개만 존재하는 번호인데 00-00-00-00-00-00 영어와 숫자로 구성되어 있다. 앞의 6자리는 제조사 번호, 뒤 6자리는 일련번호를 의미한다.
<br/></p>
<p>이러한 MAC주소는 데이터를 송수신 할때 목적지와 출발지의 주소 역할을 하고 헤더에 이 주소들이 들어간다.
예를들어 pc1의 MAC주소가 11-11-11-11-11-11이고 pc2의 MAC주소가 22-22-22-22-22-22이라면 pc1에서 2로 데이터를 전달할 때 헤더에는 목적지 22-22-22-22-22-22 출발지 11-11-11-11-11-11의 정보가 포함되어 데이터가 어디서 어디로 보내야하는지를 알고 해당 주소에만 데이터를 보내게 해준다.</p>
<p>이는 아래의 이미와 같다.
<img src="https://images.velog.io/images/sad_wf/post/f18b11fe-5799-4320-9b42-790141a34053/image.png" alt="">
이미지 출처 : 모두의 네트워크 _ 도서
<br/></p>
<p>그런데 이걸 공부하면서 생각이 들었던 궁금증이 있다. 만약 pc1에서 2와 3에 동시에 데이터를 전달할 경우 이미지의 목적지 MAC주소가 두개 붙어서 전달되는 걸까?</p>
<p>정답은 X</p>
<p>내가 이해한 것이 맞다면 그저 목적지 MAC 주소가 다른 데이터를 두번 보내게 된다.</p>
<h4 id="스위치-1">스위치</h4>
<p>스위치 또는 스위칭 허브라고 불리는 이 장비는 허브와 겉모습은 동일하게 생긴 장비다.
다만 스위치의 내부에는 <strong>MAC주소 테이블</strong>이 존재하는데 이는 스위치의 포트 번호와 해당 포트와 연결된 장비의 MAC주소를 등록시킨 데이터 베이스라고 한다.
<img src="https://images.velog.io/images/sad_wf/post/307ed055-eb5a-4131-ba84-6935fb237618/image-2.png" alt="">
이미지 출처 : 모두의 네트워크 _ 도서
<br/></p>
<p>이미지처럼 MAC주소가 스위치에 저장되고 목적지에 맞게 MAC주소를 가진 포트에만 데이터를 전달해준다.</p>
<h4 id="mac주소-테이블에-주소가-없다면">MAC주소 테이블에 주소가 없다면?</h4>
<p>이 경우에는 목적지의 주소를 모르기 때문에 모든 pc에 데이터를 전달해버리는데 이 것을 <strong>플러딩</strong>이라고 한다.
다만 이러한 문제는 <strong>ARP</strong>프로토콜에 의해서 해결이 가능하다.</p>
<p>목적지 컴퓨터의 IP주소를 이요하여 MAC주소를 찾기 위한 프로토콜로 목적지 주소를 모를 경우 이 주소를 알아내기 위해서 <strong>ARP</strong>요청을 하여 목적지의 주소를 알아내어 출발지 컴퓨터에서 해당 IP와 MAC주소의 매핑 정보를 메모리에 보관(ARP 테이블)한다. 그리고 이후 데이터 통신은 이 보관된 정보를 참고하여 전송한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TCP/IP 모델]]></title>
            <link>https://velog.io/@sad_wf/TCPIP-%EB%AA%A8%EB%8D%B8</link>
            <guid>https://velog.io/@sad_wf/TCPIP-%EB%AA%A8%EB%8D%B8</guid>
            <pubDate>Sun, 20 Mar 2022 14:18:39 GMT</pubDate>
            <description><![CDATA[<h2 id="통신-규격">통신 규격</h2>
<p>네트워크에서 데이터를 주고 받기 위한 통신 규격이 있다. OSI 표준 모델과 TCP/IP 모델이 있다.</p>
<p><img src="https://images.velog.io/images/sad_wf/post/715118af-8b88-4e2b-896a-c526f34e74f9/TCP:IP.jpg" alt="">
<br/></p>
<h2 id="osi-표준-모델">OSI 표준 모델</h2>
<p>국제 표준화기구(ISO)에서 만든 통신 규격으로 위의 이미지와 같이 7계층으로 이루어져 있다. 위에서 부터 순서대로</p>
<p>7계층 <strong>응용 계층</strong></p>
<ul>
<li>이메일, 파일전송, 웹사이트 조회 등 애플리케이션에 대한 서비스를 제공한다.</li>
</ul>
<p>6계층 <strong>표현 계층</strong></p>
<ul>
<li>문자 코드, 압축, 암호화 등 데이터를 변환한다.</li>
</ul>
<p>5계층 <strong>세션 계층</strong></p>
<ul>
<li>세션 체결, 통신 방식을 결정한다.</li>
</ul>
<p>4계층 <strong>전송 계층</strong></p>
<ul>
<li>신뢰할 수 있는 통신을 구현한다.</li>
</ul>
<p>3계층 <strong>네트워크 계층</strong></p>
<ul>
<li>다른 네트워크와 통신하기 위해 경로설정 및 논리 주소를 결정하는 역할을 한다.</li>
</ul>
<p>2계층 <strong>데이터 링크 계층</strong></p>
<ul>
<li>네트워크 기기간의 데이터 전송 및 물리조소를 결정한다.</li>
</ul>
<p>1계층 <strong>물리 계층</strong></p>
<ul>
<li>물리적인 견결과 전기 신호를 변환 및 제어한다.
<br/><br/><br/><br/></li>
</ul>
<h2 id="tcpip-모델">TCP/IP 모델</h2>
<p>OSI 모델은 현대에서 잘 사용하지 않고 TCP/IP 모델을 사용하는데 OSI 모델의 7계층을 4계층으로 압축한 형태를 지닌다</p>
<p>4계층 <strong>응용 계층</strong></p>
<ul>
<li>OSI의 7계층부터 5계층의 역할을 한다.</li>
</ul>
<p>3계층 <strong>전송 계층</strong></p>
<ul>
<li>OSI의 4계층과 동일한 신뢰할 수 있는 통신을 구현한다.</li>
</ul>
<p>2계층 <strong>인터넷 계층</strong></p>
<ul>
<li>OSI의 4계층과 동일한 다른 네트워크와 통신하기 위해 경로설정 및 논리 주소를 결정하는 역할을 한다.</li>
</ul>
<p>1계층 <strong>네트워크 접속 계층</strong></p>
<ul>
<li>OSI의 2계층부터 1계층의 역할을 한다.
<br/><br/><br/><br/></li>
</ul>
<hr>
<h2 id="데이터-송수신-과정">데이터 송수신 과정</h2>
<h3 id="데이터-송신-측">데이터 송신 측</h3>
<p>두 모델에서 데이터를 전송하는 송신 측에서는 4계층(7계층)부터 1계층까지 순차적으로 거치게 되는데 응용 단계에서 데이터를 만들고 각 계층을 지날 때마다 헤더를 붙여서 전송한다. 
*1계층의 경우는 헤더와 함께 트레일러를 함께 전달한다.
<br/></p>
<h3 id="데이터-수신-측">데이터 수신 측</h3>
<p>송신과는 역순으로 1계층부터 4계층(7계층)으로 전달되며, 헤더를 하나씩 제거하면서 진행된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SPA (Single Page Application)]]></title>
            <link>https://velog.io/@sad_wf/SPA-Single-Page-Application</link>
            <guid>https://velog.io/@sad_wf/SPA-Single-Page-Application</guid>
            <pubDate>Sat, 19 Mar 2022 07:39:03 GMT</pubDate>
            <description><![CDATA[<h2 id="spasingle-page-application란">SPA(Single Page Application)란?</h2>
<p><img src="https://images.velog.io/images/sad_wf/post/e2d42151-74d5-4dca-b638-a967a1fb12cc/image.png" alt=""><a href="https://www.excellentwebworld.com/what-is-a-single-page-application/">이미지 출처</a>
<br/></p>
<h3 id="traditional-web"><strong>Traditional Web</strong></h3>
<p>전통적인 웹의 동작 방식은 페이지에서 인터렉션이 일어날 때마다 html페이지를 서버에 새롭게 요청하는 방식이다.</p>
<ul>
<li>인터렉션이 있을 때마다 서버에 지속적으로 요청을 하기 때문에 서버에 부하를 준다.
<br/><br/><br/></li>
</ul>
<h3 id="spa-web"><strong>SPA Web</strong></h3>
<p>1개의 페이지로 이루어져 동적으로 데이터를 불러오는 애플리케이션을 의미한다.</p>
<h4 id="장점">장점</h4>
<ul>
<li>서버에 요청이 적어 부하를 적게 준다.</li>
<li>필요한 부분만 동적으로 데이터를 요청하기 때문에 반응이 빠르다.</li>
</ul>
<h4 id="단점">단점</h4>
<ul>
<li><p>초기 렌더링 속도
SPA는 서버에서 모든 것을 요청 후 사용자에게 보여주기 때문에 앱의 규모가 커지면 자바스크립트 파일 등의 규모가 커지게 되어 첫 렌더링 과정에서 속도가 느려질 수 있다.</p>
</li>
<li><p>SEO의 문제
전통적인 웹의 경우 검색엔진에서 모든 페이지를 읽어내어 웹에 노출시켜준다. 
그러나 SPA는 1개의 페이지에서 동적으로 내용이 바뀌어 정보를 읽어오기 힘들고 검색엔진에 노출되지 않는 문제가 생긴다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2차 프로젝트 종료]]></title>
            <link>https://velog.io/@sad_wf/2%EC%B0%A8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%A2%85%EB%A3%8C</link>
            <guid>https://velog.io/@sad_wf/2%EC%B0%A8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%A2%85%EB%A3%8C</guid>
            <pubDate>Sun, 26 Dec 2021 06:46:53 GMT</pubDate>
            <description><![CDATA[<blockquote>
2차 프로젝트를 끝내고 그동안 작업했던 내용과 과정을 돌아보며...

</blockquote>

<h1 id="남의집-프로젝트"><strong>남의집 프로젝트</strong></h1>
<p>취향 공유 커뮤니티 서비스 남의집을 모티브로 제작하게 된 남의집(GUYSHOUSE) 팀 프로젝트입니다.
짧은 프로젝트 기간동안 새로운 기술을 사용하여 만들어야 했기에 몇몇 기능들을 제외 및 변경하였습니다.
<br></p>
<h3 id="개발-인원-및-기간">개발 인원 및 기간</h3>
<p>개발기간 : 2021/12/13 ~ 2021/12/24
개발 인원
Front-End 3명 : <strong>김태영</strong>, 김상훈, 황성재
<a href="https://github.com/Moro-yong/27-2nd-GuysHouse-frontend.git">Front-end github</a> 링크</p>
<p>Back-End 3명 : 고민혁, 박세용, 유민혁
<br><br></p>
<p><strong>적용 기술 및 구현 기능 적용 기술</strong>
<strong>Front-End</strong> : JavaScript, React.js, SASS, React-router-dom
<strong>Back-End</strong> : Django, Python, MySQL
<strong>Common</strong> : Git, Github, Slack, Trello, Notion
<br></p>
<p><strong>[프로젝트 영상]</strong> <a href="https://www.youtube.com/watch?v=F6Sg-UZp1NY&amp;feature=youtu.be">https://www.youtube.com/watch?v=F6Sg-UZp1NY&amp;feature=youtu.be</a>
<br><br></p>
<hr>
<br>

<h2 id="내가-구현한-기능">내가 구현한 기능</h2>
<p><strong>Kakao social Login</strong></p>
<ul>
<li>kakao developers 문서 참고</li>
<li>Kakao SDK for JavaScript를 이용한 로그인,로그아웃, 연결 끊기 기능 </li>
<li>카카오 access_token을 fetch로 전달 및 로그인 토큰 localStorage에 저장</li>
<li>.env에 환경변수 저장 및 사용
<img src="https://images.velog.io/images/sad_wf/post/3b39521f-b514-4884-ba5d-7b5760cf9649/kakaologin.gif" alt="">
<br><br></li>
</ul>
<p><strong>예약 페이지</strong></p>
<ul>
<li>textarea를 map()으로 반복 및 textarea Auto Height 적용</li>
<li>textarea 내부 텍스트 Count</li>
<li>state의 값에 따라 조건부 버튼 활성화</li>
<li>동적 라우팅, useParams 사용하여 데이터 가져오기
<img src="https://images.velog.io/images/sad_wf/post/84cd1bbb-bba3-4caf-97d5-3d88cf6024c1/%E1%84%8B%E1%85%A6%E1%84%8B%E1%85%A3%E1%86%A8%E1%84%91%E1%85%A6%E1%84%8B%E1%85%B5%E1%84%8C%E1%85%B5.gif" alt="">
<br><br></li>
</ul>
<p><strong>Mypage</strong></p>
<ul>
<li>state 값을 변경하여 3가지 요소 중 한 가지만 active되도록 onClick 이벤트 작성
<img src="https://images.velog.io/images/sad_wf/post/65f4915f-a8ce-4837-aace-c7fc57a57a11/ezgif.com-gif-maker.gif" alt="">
<br><br></li>
</ul>
<hr>
<br>

<h2 id="아쉽지만-끝까지-해낼-수-있었다">아쉽지만 끝까지 해낼 수 있었다</h2>
<p><strong>각자 잘 하더라도 소통은 중요하다</strong></p>
<p>이번 프로젝트는 1차 프로젝트를 경험하였기 때문에 전체적인 기획과 초기세팅은 어렵지 않게 진행하였다. 그러나 새로운 기술을 사용하게 되었고
팀의 성격이 다르다보니 정리나 프로젝트 진행에 있어서는 다소 차이가 있었다. 게다가 각자 한번씩 경험했던 것을 하다보니 1차에 비해 소통이 조금 뜸해졌는데 그럼에도 각자 맡은 일은 잘 해나갔다. 문제는 그 이후 서로 만든 것들을 merge/ 백엔드와 연결하면서 중간중간 소통하지 않았던 부분들이 문제가 되어 돌아왔다.
다행이도 문제를 찾은 후에 빠르게 문제를 고치고 다시 소통하여 프로젝트를 끝까지 해냈지만 1차 프로젝트에서 소통을 강조하였는데도 2차에서 이렇게 행동한 것에 대한 아쉬움을 느꼈다.</p>
<p><strong>이번 프로젝트에서 좋았던 점은</strong></p>
<ol>
<li>소통이 부족했지만 이를 인식한 후 빠르게 개선하여 프로젝트를 끝낼 수 있었다는 것</li>
<li>외부 API를 사용하여 로그인 기능을 만들어 본 것</li>
<li>기획 부분에서 1차와 다르게 전체적인 팀 스케줄과 시간을 확인하고 필수와 추가 기능을 나누어 일정을 관리한 것</li>
</ol>
<p><strong>아쉬운 점</strong></p>
<ol>
<li>추후 빠르게 개선하였지만 소통이 부족하여 일정이 얼마남지 않은 상황에서 문제들이 생긴 것</li>
<li>여러 기능을 만들다보니 한 기능을 더 깊게 알아보지 못한 것</li>
</ol>
<br>

<h2 id="기록으로-남겨야-나의-것이-된다">기록으로 남겨야 나의 것이 된다.</h2>
<p><strong>외부에서 API를 받아와 사용하기...</strong></p>
<p>웹사이트를 제작할 때 모든것을 직접 만들지는 않는다고 한다. 대부분은 라이브러리와 같은 이미 만들어진 것을 가져와서 사이트에 맞게 변경하여 사용하는데 그런 종류 중 하나로 이번에 제작한 카카오 소셜 로그인이 있다.
기능부터 레이아웃까지 모든 것이 만들어져있고 그것을 가져다 쓰기만 하면 되는데 이게 그냥 control c/v로 되는 것은 아니다보니 여러가지 시행착오가 있었다.</p>
<p>게다가 같은 로그인 기능이지만 REST API, Javascript 등 만드는 방법 또한 여러가지라서 어떤 것이 나의 상황과 맞는 것인지도 확인하고 사용해야 했다.</p>
<p>이번에는 Javascript 키를 사용했는데 사용한 이유는 팝업으로 사용하기 위해서였다.
내가 공식문서를 재대로 이해한 것이 맞다면 REST API와 Javascript를 사용할 수 있는데 이 중에서 팝업으로 만들 수 있는 것은 후자에 속했다.
<br><br></p>
<p><strong>선택한 요소 강조</strong></p>
<p>Textarea의 높이를 변경하기 위해서는 css가 아닌 js를 사용해야 한다고 합니다.
게다가 크롬에서 Textarea tag를 사용하면 내용에 따라 높이가 늘어나는게 아닌 스크롤이 생긴다.</p>
<pre><code class="language-js">  const [textColor, setTextColor] = useState([true, false, false]);

  const changeColor = index =&gt; {
    const defaultState = Array(3).fill(false);
    // 함수가 실행될 때 Array(3)은 [undefined, undefined, undefined]을 만들고 .fill(false)은 3개의 값을 false로 채운다
    defaultState[index] = true;
    // 인자로 받은 index의 값을 true로 바꾸어 준다
    setTextColor(defaultState);
  };

--------------------------------------------------------------------------

  return (
        &lt;ReservationListContainer&gt;
          {DEFALUT_DATA.map((list, index) =&gt; {
            return (
              &lt;ReservationButton
                onClick={() =&gt; changeColor(index)}
                textColor={textColor[index]}
                key={index}
              &gt;
                &lt;Count textColor={textColor[index]}&gt;{list.numbers}&lt;/Count&gt;
                {list.title}
              &lt;/ReservationButton&gt;
            );
          })}
        &lt;/ReservationListContainer&gt;

--------------------------------------------------------------------------

const Count = styled.span`
  margin-bottom: 8px;
  color: ${props =&gt; (props.textColor ? &#39;orange&#39; : &#39;gray&#39;)};
`;</code></pre>
<p><br><br></p>
<p><strong>Textarea Auto Height</strong></p>
<p>Textarea의 높이를 변경하기 위해서는 css가 아닌 js를 사용해야 한다고 합니다.
크롬에서 Textarea tag를 사용하면 내용에 따라 높이가 늘어나는게 아닌 스크롤이 생기게 되어있다</p>
<pre><code class="language-js">const MAX_ROW = 20;
const TEXTAREA_LINEHEIGHT = 16;

export default function TextArea({
  id,
  context,
  checkbox,
  answers,
  setAnswers,
}) {
  const [textHeight, setTextHeight] = useState(5);

  const changeInput = event =&gt; {
    const { name, value } = event.target;
    const currentRows = ~~(event.target.scrollHeight / TEXTAREA_LINEHEIGHT);
    const previousRows = event.target.rows;

    if (currentRows === previousRows) {
      event.target.rows = currentRows;
    }
    if (currentRows &gt;= MAX_ROW) {
      event.target.rows = MAX_ROW;
    }

    setTextHeight(currentRows &lt; MAX_ROW ? currentRows : MAX_ROW);

    setAnswers({
      ...answers,
      [name]: value,
    });
  };

**뒤늦게 알게 된 사실**
  위와 같이 작성하게 되면 자동으로 높이가 늘어나지만 텍스트를 지웠을 경우 높이가 줄어들지 않았다;;
  이 부분은 추후 수정해야겠다.</code></pre>
<br>

<p><strong>~~ 연산자</strong></p>
<p>Math.floor()와 동등하게 쓰이는 연산자
자세한 내용은 다른 글에 작성하여 링크로 남기겠습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹브라우저 스크롤 높이 가져오기]]></title>
            <link>https://velog.io/@sad_wf/window.scrollTo-window.scrollY-window.scrollX</link>
            <guid>https://velog.io/@sad_wf/window.scrollTo-window.scrollY-window.scrollX</guid>
            <pubDate>Sun, 19 Dec 2021 11:53:44 GMT</pubDate>
            <description><![CDATA[<h2 id="windowpagexoffset--windowscrollx">Window.pageXOffset / Window.scrollX</h2>
<p>팀 프로젝트를 진행하면서 알게된 함수로 <code>문서의 현재 스크롤 높이를 px로 반환</code>한다.</p>
<pre><code class="language-js">window.scrollY //보고 있는 웹의 세로(높이 값)을 보여준다
window.scrollX //보고 있는 웹의 가로(너비 값)을 보여준다

Window.pageXOffset //보고 있는 웹의 세로(높이 값)을 보여준다
Window.pageXOffset //보고 있는 웹의 가로(너비 값)을 보여준다</code></pre>
<p><strong>주의!</strong>
Window.scrollX의 경우 오래된 브라우저와 일부 모바일 환경에서 지원하지 않을 수 있기 때문에
Window.pageXOffset을 사용하는 것이 더 좋은 선택일 수 있다.</p>
<h2 id="windowscrollto">window.scrollTo()</h2>
<p>함수의 이름으로 어느정도 유추할 수 있는 정말 정직한 이름을 가진 함수로 원하는 위치로 스크롤을 이동시켜 주는 기능을 한다.
우리가 웹 사이트에서 <code>TOP</code> 또는 <code>맨 위로</code> 와 같은 버튼을  눌렀을 때 특정 위치로 이동시켜주는 이벤트를 만들 경우 자주 사용하게 된다.</p>
<pre><code class="language-js">window.scrollTo({top:0, left:0, behavior:&#39;auto&#39;});</code></pre>
<p>위와 같이 CSS속성을 사용하여 작성하면 top, left에 맞는 위치로 이동한다.
behavior는 애니메이션 효과를 지정하는 속성으로 auto가 기본값으로 클리하면 순간이동 하듯이 바로 이동되고 smooth를 사용하면 부드럽게 이동한다.</p>
<p>다른 사용법으로 파라미터로 변수를 받아 사용할 수 있다.</p>
<pre><code class="language-js">window.scrollTo(x, y)</code></pre>
<p><img src="https://images.velog.io/images/sad_wf/post/81197fb1-d2e8-4fcb-be50-a6b08138710b/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.55.18.png" alt=""></p>
<p>예시는 React에서 사용했던 것으로 className가 topButton인 span에 onClick이벤트를 주어 handleTop 함수 실행하면 최상단으로 부드럽게 이동해주는 기능을 만들었다.
추가로 span에 인라인 스타일로 스크롤 높이가 260px이하일 경우 렌더를 하지 않도록 하여 최상단에서는 버튼이 보이지도 눌리지도 않게 하였다.</p>
<p><br><br><br></p>
<blockquote>
*틀린 내용이나 더 좋은 방법을 알려주신다면 더 공부해서 수정하도록 하겠습니다 ^^
</blockquote>]]></description>
        </item>
        <item>
            <title><![CDATA[2차 팀 프로젝트 1주차 종료]]></title>
            <link>https://velog.io/@sad_wf/2%EC%B0%A8-%ED%8C%80-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1%EC%A3%BC%EC%B0%A8-%EC%A2%85%EB%A3%8C</link>
            <guid>https://velog.io/@sad_wf/2%EC%B0%A8-%ED%8C%80-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1%EC%A3%BC%EC%B0%A8-%EC%A2%85%EB%A3%8C</guid>
            <pubDate>Sun, 19 Dec 2021 09:22:28 GMT</pubDate>
            <description><![CDATA[<blockquote>
2차 프로젝트 1주차 종료

</blockquote>

<h1 id="branch-프로젝트"><strong>Branch 프로젝트</strong></h1>
<p>개인이 호스트가 되어 취향이 담긴 개인 공간에 모여 대화를 나누는 커뮤니티입니다. 1차 프로젝트와는 다르게 기존 사이트의 컨셉과 기능을 그대로 사용하여 클론하였습니다.
다만 메인페이지와 둘러보기 페이지의 기능을 나눌 필요가 없다고 생각되어 메인에서 둘러보기 기능을 사용하도록 하였습니다.</p>
<h3 id="개발-인원-및-기간">개발 인원 및 기간</h3>
<p>개발기간 : 2021/12/13~2021/12/24(종료 예정)
프론트엔드 개발자 3명
백엔드 개발자 3명</p>
<p>적용 기술 및 구현 기능 적용 기술
<strong>Front-End</strong> : JavaScript, React.js, Styled-Components, React-router-dom
<br></p>
<h3 id="내가-구현한-기능">내가 구현한 기능</h3>
<p><strong>Kakao social Login</strong></p>
<ul>
<li>카카오 소셜 로그인 javascript 키를 활용하여 로그인,로그아웃,회원탈퇴 기능 구현</li>
<li>카카오 서버로부터 전달받은 access_token을 fetch로 백엔드에 전달하여 로그인 토큰을 받은 후 localStorage에 저장</li>
<li>카카오 키와 같은 예민한 데이터를 .env에 변수로 저장</li>
</ul>
<p><strong>Mypage</strong></p>
<ul>
<li>state 값을 변경하여 3가지 요소 중 한 가지만 active되도록 onClick 이벤트 작성</li>
</ul>
<p><strong>예약 페이지</strong></p>
<ul>
<li>여러개의 textarea 데이터를 state에 저장</li>
<li>styled-components 조건부 렌더링
<br><br></li>
</ul>
<hr>
<br>

<h2 id="처음은-언제나-어렵다">처음은 언제나 어렵다</h2>
<p><strong>새로운 기술 styled-component</strong></p>
<p>1차 프로젝트에서 사용했던 sass는 css와 작성법에서 크게 차이가 있지는 않았다. 그러나 2차 프로젝트에서 사용중인 styled-component는 기존의 기술들과 상당부분에서 차이가 있었고 이를 익히는데 오랜 시간이 걸리고 있다. 사용한지 1주일이 지난 지금은 어느정도 익숙해 졌지만 아직도 모르는 작성법이 있을 것이다. 부족한 부분은 찾아서 해결하는 것이 개발자의 기본 소양이기에 지금은 프로젝트를 진행하는 것을 위주로 하지만 그때 그때 필요한 것이 있다면 찾아서 해결해야겠다.</p>
<h2 id="기록으로-남겨야-나의-것이-된다">기록으로 남겨야 나의 것이 된다.</h2>
<p><strong>외부에서 API를 받아와 사용하기...</strong></p>
<p>웹사이트를 제작할 때 모든것을 직접 만들지는 않는다고 한다. 대부분은 라이브러리와 같은 이미 만들어진 것을 가져와서 사이트에 맞게 변경하여 사용하는데 그런 종류 중 하나로 이번에 제작한 카카오 소셜 로그인이 있다.
기능부터 레이아웃까지 모든 것이 만들어져있고 그것을 가져다 쓰기만 하면 되는데 이게 그냥 control c/v로 되는 것은 아니다보니 여러가지 시행착오가 있었다.</p>
<p>게다가 같은 로그인 기능이지만 REST API, Javascript 등 만드는 방법 또한 여러가지라서 어떤 것이 나의 상황과 맞는 것인지도 확인하고 사용해야 했다.</p>
<p>이번에는 Javascript 키를 사용했는데 사용한 이유는 팝업으로 사용하기 위해서였다.
내가 공식문서를 재대로 이해한 것이 맞다면 REST API와 Javascript를 사용할 수 있는데 이 중에서 팝업으로 만들 수 있는 것은 후자에 속했다.</p>
<p><img src="https://images.velog.io/images/sad_wf/post/e69c1e82-e212-49fe-b14f-c0f11ad4797c/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.10.03.png" alt="">
<br></p>
<p><strong>한개를 해결하면 꼭 다른 문제가 생긴다!</strong></p>
<p>개발이 참 재밌는게 문제가 생겼을 때 열심히 고민하고 검색하여 해결하면 다른 문제가 생긴다는 것이다. 이게 스트레스이기도 한데 이걸 또 해결하는 재미가 쏠쏠해서 계속 하게 되는데 Javascript 키를 사용하여 작업하니 생기는 문제가 있었다.</p>
<p>로그인과 로그아웃은 잘 되는데 다시 로그인 하려하니 아이디 입력창이 안뜨고 바로 로그인이 되었다. 이유를 찾아보니 카카오와 연결해제를 안해서 그렇다는데 이거 때문에 많이 고생했다.
일단 REST API는 이 기능이 기본적으로 제공하고 있다. 그러나 Javascript 키에서는 제공하지 않고 직접 만들어야하는데 아무리 찾아봐도 알 수가 없었는데 한 사이트에서 <code>Kakao.Auth.loginForm</code>를 사용하라는 글을 보고 아래와 같이 적용해보니 잘 되었다.
이렇게 문제를 해결하는 짜릿함이 코딩의 맛인거 같다. 그런데 어떻게 공식문서에도 없는 것을 글을 작성하신 분은 알고 계신 것일까?...</p>
<p><img src="https://images.velog.io/images/sad_wf/post/1dca26b7-de7d-4a13-917c-9c0106abd15b/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-12-19%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.18.29.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[함께 했기에 나를 볼 수 있는 시간 (1차 프로젝트를 끝내며)]]></title>
            <link>https://velog.io/@sad_wf/%ED%95%A8%EA%BB%98-%ED%96%88%EA%B8%B0%EC%97%90-%EB%82%98%EB%A5%BC-%EB%B3%BC-%EC%88%98-%EC%9E%88%EB%8A%94-%EC%8B%9C%EA%B0%84-1%EC%B0%A8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EB%81%9D%EB%82%B4%EB%A9%B0</link>
            <guid>https://velog.io/@sad_wf/%ED%95%A8%EA%BB%98-%ED%96%88%EA%B8%B0%EC%97%90-%EB%82%98%EB%A5%BC-%EB%B3%BC-%EC%88%98-%EC%9E%88%EB%8A%94-%EC%8B%9C%EA%B0%84-1%EC%B0%A8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EB%81%9D%EB%82%B4%EB%A9%B0</guid>
            <pubDate>Sun, 12 Dec 2021 10:20:34 GMT</pubDate>
            <description><![CDATA[<p>프로젝트 소개 / 사용된 기술 / 역할 / 협업의 경험 / 잘한 점 / 아쉬운 점 / 기록하고 싶은 코드</p>
<blockquote>
위코드 팀 프로젝트(brunch 클론코딩) 2주차를 마치고...<br><br> 

<p>12월 10일. 11월 29일부터 시작한 팀 프로젝트가 끝났다.<br>
6명의 팀원이 모여서 함께 하던 첫 프로젝트였던 만큼 부족한 점도 많았고 그랬기에 아쉽지만 더 기억에 남는 시간이었다.<br>
2주간의 내가 해온 것들을 돌아보면서 정리하는 시간을 가지도록 하자.</p>
</blockquote><br>

<h2 id="모두가-함께해서-1을-만드는-것br">&quot;모두가 함께해서 1을 만드는 것!&quot;<br></h2>
<p>프로젝트 시작하기 전에 이런 질문을 들었다. <strong>&quot;프로젝트에서 가장 중요한 것이 무엇일까요?&quot;</strong> 각자 경험과 생각이 다르기 때문에 아직도 정답이 있다고는 생각하지 않는다. 그러나 정답에 더 가까운 것은 있을 것이다. 
내가 생각했던 가장 중요한 것은 프로젝트의 완성이었다. 너무나 당연하게 생각할 수도 있지만 위코드를 오기전에 디자이너로 일하면서 가장 중요한 것은 시간내에 <strong>&quot;클라이언트가 원하는 결과물을 제공하는 것&quot;</strong>이었다. 여기서 중요한 것은 &quot;내가 완성이라고 생각하는 것&quot;이 아닌 &quot;클라이언트가 원하는 것&quot;이었다.</p>
<p>나는 예술가가 아니라 원하는 것을 대신 제공해 주는 사람이다. 내가 옳다고 생각하더라도 타인이 아니라고하면 최종적으론 아닌 것이다. 그렇기에 나의 생각과 경험을 그대로 풀어내는 것이 아닌 클라이언트와 조율하는 과정이 필요하다. 결국 나 혼자서는 결과물을 만들어 낼 수 없다. 
(클라이언트가 전적으로 모든 것을 맡기지 않는 이상은 그렇다)</p>
<p>다시 질문으로 돌아가서 <strong>&quot;프로젝트에서 가장 중요한 것이 무엇일까요?&quot;</strong> 의 질문에 답으로 말씀해주신 것이 <strong>&quot;모두가 함께해서 1을 만든는 것&quot;</strong>이라고 한다. 처음 들었을 때와 지금의 생각이 조금 달라졌다. 당시에는 너무 당연하다는 것이었지만 프로젝트가 끝난 지금 저 짧은 말에 정말 여러가지의 의미가 담겨있었다고 생각한다.</p>
<p>내가 느낀 말의 의미는 마지막에 작성해 두었다. 글을 읽고 계신 분들도 한번 생각해보는 시간을 가지는 것도 좋을거 같다.
<br><br></p>
<h2 id="시작-사람을-알아가는-것br">시작? 사람을 알아가는 것<br></h2>
<p>프로젝트의 시작은 약간의 차이는 있겠지만 Planning Meeting부터 시작해서 개발 환경 세팅 등 다양한 것이 있다.
물리적인 시작은 이러한 것들이 맞을 테지만 내가 생각한 프로젝트의 시작은 프로젝트를 함께하는 사람을 알아가는 것이라고 생각한다. 
전 직장에서도 그랬고 지금도 그렇지만 다양한 사람들과 함께하고 있다. 그렇다고 내가 만난 모든 사람을 다 기억하는가하면 그건 또 아니다. 그나마 아는 사람들도 그 사람들에 대해서 정말 잘 알고 있다고 자신할 수 있나?라고 생각해보면 절대 아니다.</p>
<p>사람은 성격, 기술, 숙련도, 환경, 취미, 신체적 특성 등 많은 것이 모두 다른데 그런 사람들이 모여서 팀 프로젝트를 하려면 작은 것부터 큰 이슈까지 다양한 일이 생기는데 이번 프로젝트 기간도 오랫동안 함께하기에 다양한 이슈가 있었다.
사는 곳도, 체력, 생활 스케줄도 달라서 이슈가 생긴다. 때로는 피곤해서, 교통에 문제가 생겨서, 의도치 않은 트러블에 말려들어서 프로젝트 일정에 문제가 생기는데 단순히 늦었다고 화를 낼 수 있을까? 실력이 부족하다고 몰아세우면서 일을 시킬 것인가? 그렇다면 이렇게 한다고 프로젝트가 성공적으로 끝날 것인가? 나는 아니라고 생각한다. 설령 프로젝트가 끝났다고 해도 다음에 또 같이 프로젝트를 함께 할 때는 어떨까? 그런 사람과 함께 프로젝트를 하고 싶을까? <strong>절대 NO!</strong> 라고 외칠 수 있다.</p>
<p>위에서 프로젝트에서 가장 중요한 것은 <strong>&quot;모두가 함께해서 1을 만든는 것&quot;</strong> 이라고 했는데 이 말의 시작이 <strong>&quot;사람을 알아가는 것&quot;</strong>이다.<br></p>
<h3 id="이야기가-필요한-시간br">이야기가 필요한 시간<br></h3>
<p>프로젝트를 한다는 것은 정말 많은 이야기를 하는 시간을 가진다라는 것이다. 대화나 소통이 아닌 &quot;이야기&quot;라고 한 이유는 무엇일까?
효율을 생각한다면 쓸데 없는 말은 줄이는 것이 좋을수도 있다. 하지만 내가 생각하기에 정말 좋은 프로젝트는 쓸데 없는 시간을 보내는 것으로 만들어 진다. 다만 쓸데 없는 시간이라고 해서 누구를 욕하거나 안좋은 얘기를 하라는 것이 아니라 함께 하기 위해서 필요한 쉬는 시간의 대화, 타인을 알아가는 이야기를 말하는 것이다.</p>
<p>타인을 알아가는 대화. 정말 다양한 이야기가 있다. 먹을 것, 취미, 어제 무엇을 했는지, 오늘, 내일 무엇을 할 예정인지... 그냥 우리가 흔히 사람을 만나서 하는 대화를 말하는 것이기에 특별한 것이 아니다. 그러나 이러한 시간을 갖는다는 것의 의미는 정말 중요하다고 느꼈다.
아무래도 오랫동안 일을하면 지칠 수밖에 없다. 더군다다 전혀 다른 분야를 공부하려하는 지금 체력적으로도 정신적으로도 힘든 시기라고 생각하는데 어떻게 사람이 하루종일 딱딱하게 코드만 보고 일에 관련된 대화만 할 것인가... 너무 끔찍한 환경이라고 생각한다. 우리에게는 재충전할 시간이 필요하다.
<br><br></p>
<h2 id="실패한다는-것br">실패한다는 것<br></h2>
<h3 id="걱정br">걱정<br></h3>
<p>프로젝트를 시작하기 전. 여러가지를 배우고 내 것으로 소화하기 위해서 노력하고 있지만 짧은 시간에 많은 정보를 소화하는 것이 쉽지 않다. 지금까지 살면서 알던 것과 전혀 다른 지식이라 더욱 힘든데 단기간에 집어 넣으려니 이해가 안되는 것 투성이다. 그와중에 팀으로 프로젝트를 하라는 말은 기대보다는 걱정부터 들었는데 &quot;내가 잘 할수 있을까? 팀한테 폐만 안끼쳐도 정말 다행일텐데...&quot;라는 생각은 누구나 할테니 그저 할 수 있는 최선의 선택으로 최대의 효율을 내기 위해서 노력하고자 했다.
자는 시간을 줄이고, 팀원과 많이 이야기 해보고, 조율하면서 내 역량으로 어느 정도의 일을 소화할 수 있을지 생각하고 시간은 한정적이니 어느 기능을 중점으로 구현하고, 기능을 제외하거나 변형시킬지 정하는 등.
걱정하는 것을 나쁘다고 하지는 않아도 될거 같은게 걱정을 하기 때문에 이렇게 준비를 하는 것일테니 이제야 스타트라인에 올라선 지금 적절한 걱정과 그에 맞는 준비를 하는 것이 좋은거 같다.</p>
<h3 id="내가-더-잘-했다면br">내가 더 잘 했다면...<br></h3>
<p>그러나 세상일이 생각한데로 척척 돌아가주던가... 막상 프로젝트를 시작하고 JavaScript, React, 데이터 연결 등 많은 곳에서 삐그덕 거리더니 오류와 어떻게해야 만들수 있는지 알 수 없는 로직까지 참 다양한 문제가 많이 발생했다. 시간도 내가 생각했던 기간을 훌쩍 넘기고 프로젝트가 끝난 지금도 몇몇 기능은 처음 생각한 것과는 다소 다른 기능이 되어있다.</p>
<p>이렇게 문제가 하나 생길 때마다 조급해지는 것은 어쩔 수 없던거 같다. 거기에 다른 팀원들은 모르는 것도 찾아서 척척 만드는 것을 보면서 더욱 그랬다. 팀원 중 한 분은 나에게 도와달라는 말을 많이 하시고 매번 고맙다는 말과 잘한다는 말을 해주시는데 내가 보기에는 그분이 더 대단하다고 생각한다.
괜히 도와드린다고 가서 시간만 뺏는게 아닌가 생각이 들정도로 검색으로 필요한 것을 잘 찾아 적용하시는데 보면서 그렇게 부러울 수가 없었다.</p>
<p>프로젝트가 끝난 지금 결과물을 보면 여전히 버그가 많고 많은 기능이 삭제되어서 아쉽다. 잠을 조금 더 줄이면 됬을까? 더 많이 더 오랫동안 코드를 봤어야 했나. 어떻게 하면 더 좋은 결과물을 냈을지는 아직도 잘 모르겠지만 &quot;내가 더 잘 했다면...&quot;이라는 생각은 떨칠 수가 없다.</p>
<h3 id="완벽하지-않아도-괜찮아br">완벽하지 않아도 괜찮아<br></h3>
<p>그렇지만 완벽할 필요는 없다고 생각한다. 난 이제 시작하는 것이고, 그렇기에 부족할 수밖에 없다. 그리고 그 부족한 부분은 보완해가면 된다. 이건 시간이 좀 걸릴테지만 지금 당장은 팀원이 있으니 든든하다고 느껴지는 것이 프로젝트의 매력인거 같다.
<br><br></p>
<h2 id="다시-모두가-함께해서-1을-만드는-것br">다시 &quot;모두가 함께해서 1을 만드는 것!&quot;<br></h2>
<p>길게 작성했지만 결국 중요한 것은 <strong>&quot;모두가 함께해서 1을 만드는 것!&quot;</strong> 이다.
프로젝트는 나 혼자 하는 것이 아니라 함께 하는 사람들이 있고 이들의 장점부터 단점까지 모두 가지고서 1을 만들어야한다. 누군가는 검색을 잘해서 정보를 잘 모으고, 누군가는 정리를 잘 하고, 누군가는 코드를 잘 작성한다. 내가 부족하더라도 누군가는 잘 할수 있고 혼자 생각하는 것보다 둘, 셋이 생각하니 타협 할지언정 완성되는 것을 볼수 있었다. 
아직은 완벽할 필요는 없다. 부족하기에 더 배우려고 하는 것이니 이 시간을 소중히 사용하도록 하자~</p>
<br>
<blockquote>
  2주라는 짧은 시간동안 함께한 6명의 팀원과 멘토님들께 감사합니다.<br>
  어디 모난 곳 없기 즐겁게 함께 했기에 더욱 좋은 시간이었고 완벽한 팀은 아니지만 그렇기에 더 많은 것을 배울 수 있었습니다.
  2차 프로젝트도 화이팅 넘치게! 더욱 성숙한 개발자가 되어서 만나요~
</blockquote>




]]></description>
        </item>
    </channel>
</rss>