<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>93_0312.log</title>
        <link>https://velog.io/</link>
        <description>항상 생각하는 개발자</description>
        <lastBuildDate>Mon, 10 Jan 2022 01:31:56 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>93_0312.log</title>
            <url>https://images.velog.io/images/93_0312/profile/0bb456af-6318-41cd-bdaa-caf7b83ecd49/social.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. 93_0312.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/93_0312" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[컴포넌트 언마운트 시키기]]></title>
            <link>https://velog.io/@93_0312/%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%96%B8%EB%A7%88%EC%9A%B4%ED%8A%B8-%EC%8B%9C%ED%82%A4%EA%B8%B0</link>
            <guid>https://velog.io/@93_0312/%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-%EC%96%B8%EB%A7%88%EC%9A%B4%ED%8A%B8-%EC%8B%9C%ED%82%A4%EA%B8%B0</guid>
            <pubDate>Mon, 10 Jan 2022 01:31:56 GMT</pubDate>
            <description><![CDATA[<pre><code>function App() {
  const [useEffectRender, setUseEffectRender] = useState(true);

  return (
    &lt;div className=&quot;App&quot;&gt;
      {useEffectRender &amp;&amp; &lt;UseEffectExample /&gt;}
      &lt;button onClick={() =&gt; {setUseEffectRender(!useEffectRender)}}&gt;언마운트 시키기&lt;/button&gt;
    &lt;/div&gt;
  );
}

export default App;</code></pre><p>버튼을 누르고 useEffectRender값이 true / false를 반복하면서 컴포넌트가 마운트, 언마운트 되도록 동작하게 하는 코드... useEffect return에 적어준 언마운트시 실행되어야하는 로직들이 제대로 실행되는지 확인해볼 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SWR 정리]]></title>
            <link>https://velog.io/@93_0312/SWR-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@93_0312/SWR-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sun, 02 Jan 2022 09:26:41 GMT</pubDate>
            <description><![CDATA[<p>SWR - 데이터 가져오기를 위한 React Hooks</p>
<p>데이터 가져오기를 위한 React Hooks라고 적혀있듯, SWR은 데이터 가져오기에 특화된 Hook이다.
Post가 불가능 한 것은 아니지만, Axios등에 비해 큰 이점이 없다.</p>
<p>Axios를 사용한다면, 필요할 때마다 API를 호출해야 데이터가 갱신되지만, SWR은 여러 경우에서 자동으로 재검증을통해 데이터를 업데이트 해주는 기능이 있음.</p>
<p>SWR의 기본적인 사용방법</p>
<p>const fetcher = (...args) =&gt; fetch(...args).then(res =&gt; res.json())</p>
<p>-&gt; fetcher는 데이터를 불러오는 함수, axios, fetch 등 어떤것을 이용해도 상관없으며 데이터를 불러오는 기능만 수행하면 된다.</p>
<p>{ data, error } = useSWR(key, fetcher)</p>
<p>key : 일반적으로는 데이터를 불러오는 API의 URL을 key로 사용한다.
fetcher : 데이터를 불러오는 함수</p>
<p>data : 데이터 요청의 반환값, 캐시된 데이터(?) 또는 새롭게 받은 데이터를 반환한다.
error : fetcher에서 반환된 에러, SWR라이브러리 기능 중 에러가 발생했을때 수행해주는 로직이 따로 있음</p>
<p>SWR의 장점 : 자동 갱신</p>
<ol>
<li>네트워크가 복구 될 때 자동으로 데이터를 재검증</li>
<li>Page를 다시 포커스하거나, Tab을 변경하였을 때 재검증</li>
<li>설정한 간격마다 데이터를 다시 불러온다.</li>
</ol>
<pre><code>useEffect
import React from &#39;react&#39;;
import { useState, useEffect } from &#39;react&#39;;
import { getData } from &#39;./lib/api&#39;;

const App = () =&gt; {
  const [data, setData] = useState(null);
  useEffect(() =&gt; {
    const data = getData();
    setData(data);
  });

  return &lt;div&gt;{data.name}&lt;/div&gt;;
}

export default App;</code></pre><pre><code>//useSWR
import useSWR from &#39;swr&#39;;
import { fetch } from &#39;./lib/api&#39;;

const App = () =&gt; {
  const { data } = useSWR(&#39;api/data/&#39;, fetch);

  return &lt;div&gt;{data.name}&lt;/div&gt;;
}

export default App;</code></pre><p>데이터를 불러오는 간단한 예제,
1:UseEffect
2:UseSWR
둘다 데이터를 받아오는 동작을 수행</p>
<p>조건부 가져오기</p>
<p>const { data } = useSWR(shouldFetch ? &#39;/api/data&#39; : null, fetcher)</p>
<p>useSWR의 기본형인</p>
<p>const {data, error} =useSWR(key, fetcher);</p>
<p>에서 key 부분에 함수를 넣어줄 수 있고, 함수가 falsy를 반환하면 SWR은 데이터 요청을 시작하지 않습니다. 이를 이용해서 조건부로 데이터를 요청하거나 요청하지 않게 만들 수 있습니다.</p>
<p>조건부 가져오기 (의존)</p>
<pre><code>function MyProjects () {
  const { data: user } = useSWR(&#39;/api/user&#39;)
  const { data: projects } = useSWR(() =&gt; &#39;/api/projects?uid=&#39; + user.id)

  if (!projects) return &#39;loading...&#39;
  return &#39;You have &#39; + projects.length + &#39; projects&#39;
}</code></pre><p>이 경우 user가 먼저 로드 되지 않았을 경우에는</p>
<p>user.id부분에서 에러를 던지게 되므로, project는 불러와지지 않습니다. (key가 falsy인 경우);</p>
<p>다음과 같은 코드형태로도 key를 fetcher에 전달할 수 있습니다. </p>
<pre><code>const { data: projects } = useSWR({ url: &#39;/api/projects&#39;, args: user }, fetcher)</code></pre><p>fetcher함수 내에서 url, args 값을 사용할 수 있습니다.</p>
<pre><code> const { data: projects } = useSWR(() =&gt; &#39;/api/projects?uid=&#39; + user.id) 대신
 const { data: projects } = useSWR({ url: &#39;/api/projects&#39;, args: user }, fetcher) 로 작성한 뒤,
 fetcher함수 내에서 args를 url뒤에 붙여주면 두 줄의 코드가 같은 동작을 수행합니다.</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[기업협업 (FLES, 3s planet 프로젝트) 후기]]></title>
            <link>https://velog.io/@93_0312/%EA%B8%B0%EC%97%85%ED%98%91%EC%97%85-FLES-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@93_0312/%EA%B8%B0%EC%97%85%ED%98%91%EC%97%85-FLES-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Tue, 31 Aug 2021 08:16:17 GMT</pubDate>
            <description><![CDATA[<h2 id="⚽-fles-인턴쉽---3s-planet-프로젝트">⚽ <strong>FLES 인턴쉽 -</strong> 3s Planet 프로젝트</h2>
<ul>
<li><p><strong>개발 기간</strong> : 2021년 8월 11일 ~ 8월 26일</p>
</li>
<li><p><strong>개발 인원</strong> :  프론트엔드 1인, 백엔드 2인</p>
</li>
<li><p><strong>사용 기술</strong> :</p>
<p>   Back-End : node.Js, TypeScript, Docker, s3</p>
<p>   Front-End : React Hooks, Styled-Component, TypeScript, Ant Design</p>
<p>   Common : AWS(EC2,RDS), RESTful API</p>
</li>
</ul>
<h2 id="클라이언트---견적문의페이지">클라이언트 - 견적문의페이지</h2>
<p><img src="https://images.velog.io/images/93_0312/post/e39ac978-9990-4a5a-8a43-3a528965c73b/7.gif" alt=""></p>
<ul>
<li><p>사용자의 견적문의 정보입력을 하나의 컴포넌트 내에서 전부 처리해주기 위해서, 조건부 렌더링을 사용했습니다.</p>
</li>
<li><p>상태관리를 위한 라이브러리로 Redux를 사용해보고 싶었지만, 규모가 그렇게 큰 프로젝트가 아니었기 때문에 FLES 직원분께서 불필요하게 Redux를 사용하지 말라고 하셔서 Hooks를 사용하는 방식을 선택하게 됬습니다.</p>
</li>
<li><p>컴포넌트 내에서는 State(Contact)를 1,2,3 숫자와 비교하기보다는 코드의 가독성을 위해서 utils/contants.ts 파일에서 각 숫자에 대응하는 변수를 만들어 준뒤, 이를 import해서 사용하는 방식을 사용했습니다.</p>
</li>
</ul>
<h2 id="api-레이어-구분">API 레이어 구분</h2>
<p><img src="https://images.velog.io/images/93_0312/post/89ac56f3-b3fe-44a6-bd92-7004c1fb04d8/image.png" alt=""></p>
<ul>
<li>기업협업을 하기 이전까지의 프로젝트에서는 Config.ts 파일에서 API주소를 export 해주고 이를 컴포넌트에서 사용하는 방식을 사용했었습니다.</li>
<li>하지만 이번 프로젝트에서는 API주소를 export하는 것이 아닌, 해당 주소와 통신한 결과값을 export해주고 컴포넌트에서는 해당 data를 바로 사용할 수 있도록 하는 방식을 사용했습니다.</li>
</ul>
<h2 id="어드민페이지---견적문의관리">어드민페이지 - 견적문의관리</h2>
<p><img src="https://images.velog.io/images/93_0312/post/f735da65-7d2c-4df2-878f-0223174c77b0/77.gif" alt=""> </p>
<ul>
<li><p>견적문의를 관리하는 부분에서는 해당문의의 진행상태를 [예정, 완료, 취소] 세가지의 상태로 변경할 수 있도록 구현했습니다.</p>
</li>
<li><p>문의현황 페이지에서는 Antd 차트라이브러리 이용해, 차트형식으로 문의현황을 표시하는 방식을 선택했습니다. 문의현황 페이지는 완성하지 못해 아쉬움이 남는 부분이었습니다...</p>
</li>
</ul>
<h2 id="후기">후기</h2>
<p>인턴십 이전의 프로젝트에서는 원하는 기능을 구현하는 것에 큰 목표를 두었기 때문에, 코드의 구조나, 폴더의 구조, 해당 코드의 위치등에 대해서 크게 신경쓰지 못한 부분이 있었습니다.</p>
<p>FLES에서 인턴십을 진행하면서, 사수님께 구현된 코드들을 테스트하기 위해서는 비즈니스로직, 마크업을 위한코드, 이를 꾸며주는 CSS코드가 각각 분리되어 있는 것이 좋다는 것을 들을 수 있었습니다. </p>
<p>이후 단순히 더 많은 기능을 구현하는 것보다 코드들을 어떻게 분리해야, 조금 더 효율적으로 코드들이 동작하고, 테스트친화적인 코드를 작성할 수 있을지에 대해서 많이 고민해보는 프로젝트였습니다.</p>
<p>또한, 코드를 작성함에 있어 처음으로 TypeScript를 사용하게 되었습니다. 처음 배워보는 TypeScript에 빠르게 익숙해지기 위해서, 협업 첫주차에는 TypeScript를 사용한 To-Do List 페이지를 만들어 보기도 했습니다. 써본적 없는 TypeScript를 프로젝트에 바로 적용하는 것이 힘들었지만, To-Do List를 만들어보며 연습해본 것을 바탕으로, 큰 어려움없이 프로젝트를 진행해 나갈 수 있었습니다. </p>
<p>인턴십 초기에 목표했던 것에 비해 구현하지 못한 부분들도 있지만, 위코드에서 빠르게 코딩을 배우는 과정에서는 전혀 생각해보지 못했던 관점(코드분리의 장점, 테스트관점)에서 많은 고민을 해볼 수 있었다는 점, 컴파일단계에서 잘못된 부분을 바로잡는 일을 도와주는 TypeScript에 대한 학습을 할 수 있었다는 점이 정말 좋았던 인턴십이었다고 생각하고, 이후 코드를 작성하는데 있어서도, 해당 고민의 결과를 적용시킬 수 있도록 계속해서 노력하겠습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[웃픈갤러리 (오픈갤러리 클론 프로젝트) 후기]]></title>
            <link>https://velog.io/@93_0312/%EC%9B%83%ED%94%88%EA%B0%A4%EB%9F%AC%EB%A6%AC-%EC%98%A4%ED%94%88%EA%B0%A4%EB%9F%AC%EB%A6%AC-%ED%81%B4%EB%A1%A0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@93_0312/%EC%9B%83%ED%94%88%EA%B0%A4%EB%9F%AC%EB%A6%AC-%EC%98%A4%ED%94%88%EA%B0%A4%EB%9F%AC%EB%A6%AC-%ED%81%B4%EB%A1%A0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Tue, 31 Aug 2021 08:15:57 GMT</pubDate>
            <description><![CDATA[<h2 id="🖼-웃픈갤러리">🖼 웃픈갤러리</h2>
<ul>
<li><p><strong>개발 기간</strong> : 2021년 7월 19일 ~ 7월 30일</p>
</li>
<li><p><strong>개발 인원</strong> :  프론트엔드 2인, 백엔드 3인</p>
</li>
<li><p><strong>사용 기술</strong> :</p>
<p>   Front-End : React Hooks, Styled-Component</p>
<p>   Back-End : Python, Django, MySQL, Bcrypt, pyJWT, Docker, s3</p>
<p>   Common : AWS(EC2,RDS), RESTful API</p>
</li>
<li><p><strong>깃허브</strong> : <a href="https://github.com/93-0312/2nd-upoonGallery-frontend">https://github.com/93-0312/2nd-upoonGallery-frontend</a></p>
</li>
</ul>
<h2 id="메인페이지">메인페이지</h2>
<p><img src="https://images.velog.io/images/93_0312/post/513cac6f-cf1a-44df-bf6e-341b9988ba98/3.gif" alt=""></p>
<pre><code>  useEffect(() =&gt; {
    fetch(
      `${J_API.DISCOVER}?sort=created-descend&amp;limit=4&amp;offset=1&amp;shape=가로형`
    )
      .then(res =&gt; res.json())
      .then(data =&gt; {
        let tempData = [data.results];
        tempData[0].push(tempData[0][0]);
        tempData[0].unshift(tempData[0][3]);
        setTopSlideData(tempData[0]);
      });
  }, []);</code></pre><pre><code>  const slideRef = React.useRef();
  const [slideIndex, setSlideIndex] = useState(1);
  const history = useHistory();

  const slideNext = () =&gt; {
    if (slideIndex &lt; 5) {
      setSlideIndex(slideIndex + 1);
      slideRef.current.style.transition = &#39;transform 0.25s&#39;;
      slideRef.current.style.transform = `translateX(-${
        (slideRef.current.scrollWidth / 6) * (slideIndex + 1)
      }px)`;
    }

    if (slideIndex === 5) {
      setSlideIndex(2);
      slideRef.current.style.transition = &#39;transform 0.001s&#39;;
      slideRef.current.style.transform = `translateX(-${
        slideRef.current.scrollWidth / 6
      }px)`;

      setTimeout(() =&gt; {
        slideRef.current.style.transition = &#39;transform 0.25s&#39;;
        slideRef.current.style.transform = `translateX(-${
          (slideRef.current.scrollWidth / 6) * 2
        }px)`;
      }, 50);
    }
  };</code></pre><ul>
<li>무한슬라이드를 구현하기 위해서, setTimeout를 채용했습니다. 슬라이드에 사용되는 이미지배열의 앞, 뒤에 첫번째이미지와 마지막이미지를 한번더 넣어 준 뒤, setTimeout 함수를 이용해 마치 무한적으로 돌아가는 슬라이드처럼 보이도록 구현했습니다.</li>
</ul>
<h2 id="리스트페이지discover">리스트페이지(Discover)</h2>
<p><img src="https://images.velog.io/images/93_0312/post/09dd9843-3429-479d-a75b-ef10f39f92d9/4.gif" alt=""></p>
<pre><code>  const imageHeightRef = useRef(null);
  const [spans, setSpans] = useState(0);
  const [load, setLoad] = useState(false);

  useEffect(() =&gt; {
    if (load) {
      const height = imageHeightRef.current.offsetHeight;
      const spans = Math.ceil(height / 10);
      setSpans(spans);
    }
    return setLoad(false);
  }, [load]);</code></pre><pre><code>const DiscoverCardItem = styled.div`
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  width: 100%;
  border: 1px solid #dfdfdf;
  border-radius: 15px;
  grid-row-end: span ${props =&gt; props.spans};
  cursor: pointer;
`;</code></pre><ul>
<li><p>마치 벽돌을 쌓아 올린듯이 보이는 Masonry 레이아웃을 구현하는데 있어, Display : column 이라는 단순한 코드로도 비슷한 형태가 구현되지만, 이 경우에는 화면에 단순히 다단처리를 해준 것으로, 컨텐츠들이 좌측부터 쌓이는 형태로 구현이 됩니다.</p>
<p>그 결과 데이터가 충분히 많지 않을때, 화면의 좌측에만 컨텐츠들이 표시되고, 우측부분은 비어있게되는 결과가 발생하게 됩니다. 따라서 조금은 더 복잡하고, 구현하는데 시간이 필요했지만, Grid형식의 코드를 통해 채워진 높이가 낮은 순서대로 컨텐츠들이 삽입되는 방식을 구현했습니다.</p>
</li>
<li><p>제가 선택한 Grid 방식의 Masonry의 동작방식
기능구현을 위해 각 Div의 Height가 필요했기 때문에 useRef를 이용해, 각 카드(높이가 서로 다른)들을 포함하는 Div에 Ref를 걸어주어 해당 Div의 Height를 구했습니다.이후 Height를 Grid의 Span 단위(row+gap)인 10px로 나눈 값을 Styled-Components의 props로 넘겨주어 카드의 높낮이마다 유동적으로 Div의 크기를 조절해주어 Masonry 레이아웃을 구현하는 방식을 선택했습니다.</p>
<p>이후 Height를 Grid의 Span 단위(row+gap)인 10px로 나눈 값을 Styled-Components의 props로 넘겨주어 카드의 높낮이마다 유동적으로 Div의 크기를 조절해주어 Masonry 레이아웃을 구현하는 방식을 선택했습니다.</p>
</li>
</ul>
<h2 id="프로젝트-후기">프로젝트 후기</h2>
<p>Front-End 개발자로서 새로운 기술을 빠르게 익히는 것이 얼마나 중요한지 배울 수 있었던 소중한 프로젝트 였습니다.</p>
<p>이번 프로젝트에서는 앞선 프로젝트때와는 달리 Front-End의 인원이 3명에서 2명으로 줄어들었습니다. 하지만, 그동안 열심히 해왔던만큼 2명이서도 3명, 4명분의 프로젝트를 완성할 수도 있겠다는 호기심과도 비슷한 자신감이 있었습니다. </p>
<p>하지만 React를 배우며, 항상 Class형 컴포넌트와 CSS를 사용했었던 것과 달리, 웃픈갤러리 프로젝트에서는 함수형 컴포넌트와, Styled-Component를 사용하게 되었습니다. 두가지 기술을 배우고 사용하는것에 추가적인 시간이 필요했고, 처음엔 불편하기도 했습니다.</p>
<p>하지만 팀원분과 함께 빠르게 기술을 습득한 뒤에는 오히려, this를 크게 신경쓰지 않아도 되는 부분, props를 통해서 CSS를 선별적으로 적용할 수 있기도 하는 부분이 오히려 프로젝트를 진행하는데 많은 도움이 된다고 느끼게 되었습니다.</p>
<p>초기에 생각했던만큼 3명, 4명분의 프로젝트를 완성하지는 못했지만, 기존에 사용하지 않았던 새로운기술들을 빠르게 배우며, 프로젝트에 적용해 볼 수 있는 좋은 기회였고, 계속해서 발전해나가는 Front-End 분야의 개발자로서, 끊임없이 공부하며 계속해서 새로운 기술을 익혀나가는 것이 중요하겠다라는 것을 느껴볼 수 있었던 소중한 경험이라고 생각합니다. </p>
<p><img src="https://images.velog.io/images/93_0312/post/469e4a10-581a-4f1f-8aa2-ffc15823148b/open.jpg" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[고기각 (정육각 클론 프로젝트) 리뷰]]></title>
            <link>https://velog.io/@93_0312/%EA%B3%A0%EA%B8%B0%EA%B0%81-%EC%A0%95%EC%9C%A1%EA%B0%81-%ED%81%B4%EB%A1%A0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@93_0312/%EA%B3%A0%EA%B8%B0%EA%B0%81-%EC%A0%95%EC%9C%A1%EA%B0%81-%ED%81%B4%EB%A1%A0-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Tue, 31 Aug 2021 08:15:43 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p><strong>개발 기간</strong> : 2021년 7월 5일 ~ 7월 16일</p>
</li>
<li><p><strong>개발 인원</strong> :  프론트엔드 3인, 백엔드 3인</p>
</li>
<li><p><strong>사용 기술</strong> :</p>
<p>   Front-End : React, SASS
   Back-End : Python, Django</p>
</li>
<li><p><strong>깃허브</strong> : <a href="https://github.com/wecode-bootcamp-korea/22-1st-Gogigak-frontend">https://github.com/wecode-bootcamp-korea/22-1st-Gogigak-frontend</a></p>
</li>
</ul>
<h2 id="메인페이지">메인페이지</h2>
<p><img src="https://images.velog.io/images/93_0312/post/eba3e2ff-56b5-4c96-8e8a-52ef246ce302/1.gif" alt=""></p>
<pre><code>componentDidMount() {
    fetch(API.SLIDE, {
      method: &#39;GET&#39;,
    })
      .then(res =&gt; res.json())
      .then(result =&gt; this.setState({ mainSlideImage: result }));

    fetch(`${API.LIST}?sort=sales`)
      .then(res =&gt; res.json())
      .then(result =&gt; this.setState({ items: result.results }));

    setInterval(this.slideNext, 3000);
  }

  slideNext = () =&gt; {
    if (this.state.slideIndex &lt; 4) {
      this.setState({ slideIndex: this.state.slideIndex + 1 }, () =&gt; {
        this.slideContainer.current.style.transition = &#39;  transform 2s&#39;;
        this.slideContainer.current.style.transform = `translateX(-${
          1184 * this.state.slideIndex
        }px)`;
      });
    } else {
      this.setState({ slideIndex: -1 });
    }
  };</code></pre><ul>
<li>React에서 제공하는 생명주기 중에서 componentDidMount를 사용하여, 사용자가 페이지에 접속했을 때, 서버와 통신하는것을 통해서, mainSlide에 표시될 이미지들을 받아온 뒤, setInterval을 걸어주어 3000ms마다 슬라이드의 이미지가 변경되도록 구현했습니다.</li>
</ul>
<h2 id="장바구니-페이지">장바구니 페이지</h2>
<p><img src="https://images.velog.io/images/93_0312/post/40ccb691-802c-4386-80b2-b3941519090e/2.gif" alt=""></p>
<pre><code>  quantityPlus = (cartItemId, cartIndex, stock) =&gt; {
    const newCartData = [...this.state.cartData];
    if (newCartData[cartIndex].quantity &lt; stock) {
      newCartData[cartIndex].quantity = newCartData[cartIndex].quantity + 1;
      this.setState({ cartData: newCartData });

      const authToken = localStorage.getItem(&#39;token&#39;);

      fetch(`${API.CART}/${cartItemId}`, {
        method: &#39;PATCH&#39;,
        headers: {
          authorization: authToken,
        },
        body: JSON.stringify({
          changeQuantity: this.state.cartData[cartIndex].quantity,
        }),
      });
    } else if (newCartData[cartIndex].quantity === stock) {
      alert(&#39;구매할 수 있는 최대수량입니다.&#39;);
    }</code></pre><ul>
<li><p>품절된 제품인 경우, 불투명하게 블라인드 처리를 해주어 품절인 것을 쉽게 알아 볼 수 있도록 처리했으며, 품절된 상품이 있는채로 구매를 시도하면 경고창이 나타나도록 구현했습니다.</p>
</li>
<li><p>장바구니 내부에서 수량을 변경할 경우, 변경될 때마다, 최종적으로 변경된 수량이 몇개인지 서버와 통신하도록 구현했습니다. 서버측에 기록되있는 총 재고 이상으로 수량을 변경할 경우 최대 수량이라는 경고창이 나타나도록 구현했습니다.</p>
</li>
</ul>
<h2 id="프로젝트-후기">프로젝트 후기</h2>
<p>함께 일한다, 협업이란 이런 것이 아닐까? 하는 것을 몸으로 느끼며 배울 수 있었던 소중한 프로젝트였습니다.</p>
<p>프로젝트를 시작하며 가장 중요한 것은, 하나의 팀이 되어 원활할 소통을 하는 것이라고 생각했기 때문에 저는 Back-End 분들의 언어를 이해하려고 노력했습니다.</p>
<p>서버와 HTTP 통신을 사용해 데이터를 전송하는 과정에서 배열이나, 객체에 대한 이야기를 많이 하게 되었습니다. {key : value, ...} 형태의 자료형을 Back-End분들은 딕셔너리라고 한다는 것을 알고 있었기 때문에, 비록 익숙하지 않은 용어였지만 딕셔너리라는 용어를 사용하는 것을 통해, 좀더 원활히 대화를 할 수 있었다고 생각합니다.</p>
<p>개인적으로 맡았던 부분 중 기억에 남는 것은, 처음엔 장바구니페이지에서 주문할 제품의 수량을 변경할때마다 매번 Body에 증가버튼을 눌렀다는 신호를 보내는 방식을 이용했으나, 문제가 있어 수량이 증가되거나 감소된 이후 최종 수량을 통신하는 방식을 사용해서 문제를 해결했던 부분입니다. Back-End분과 함께 생각하고 고민했었기 때문에, 해당 문제가 해결됬을때 서로가 큰 성취감을 느낄 수 있었던 것 같습니다.</p>
<p>처음으로 진행한 프로젝트여서 부족한점도 많았지만, 함께하기 위해서 필요한 것들에 대해 배울 수 있었던 정말 소중한 프로젝트경험이었다고 생각합니다!</p>
<p><img src="https://images.velog.io/images/93_0312/post/ef22035b-2572-41fa-99b3-8b0350e06966/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[타입스크립트,,]]></title>
            <link>https://velog.io/@93_0312/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8</link>
            <guid>https://velog.io/@93_0312/%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8</guid>
            <pubDate>Mon, 02 Aug 2021 15:00:59 GMT</pubDate>
            <description><![CDATA[<p>미션 타입스크립트 + 리액트 투두리스트 만들기.....</p>
<p>타입스크립트가 익숙하지 않은게 아니고 어떻게 돌아가는건지 이해가 안됨...
..........</p>
<p>대충 변수에 타입을 지정해준다.. 이런건 알겠으나, 객체를 선언해주고, 이를 이용한 배열타입의 State를 지정해 주었을 때, 해당 State.id 같은 것을 사용하려고 했을 때 등,,, 뭔가를 거쳐서 뽑아내려고 할 때..? 기타 등등 아직 뒤죽박죽 내가 뭘 치고있는지 잘 모르겠다.. 어지럽네..</p>
<p>그래도 일단 시작은 했으니,, 어느정도만 넘어서면 쉽게 사용할 수 있으리~~!!!!!!!!!!!!!!!!!!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Masonry layout ]]></title>
            <link>https://velog.io/@93_0312/Masonry-layout</link>
            <guid>https://velog.io/@93_0312/Masonry-layout</guid>
            <pubDate>Mon, 26 Jul 2021 00:57:07 GMT</pubDate>
            <description><![CDATA[<p>기능구현 중</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Props]]></title>
            <link>https://velog.io/@93_0312/Props</link>
            <guid>https://velog.io/@93_0312/Props</guid>
            <pubDate>Mon, 26 Jul 2021 00:55:50 GMT</pubDate>
            <description><![CDATA[<h3 id="1-props">1. Props</h3>
<p>props : properties (속성)
컴포넌트의 속성 값 : 모든 컴포넌트는 props를 내장하고 있다.
부모 컴포넌트로부터 전달 받은 데이터(정보)를 지니고 있는 객체
부모 컴포넌트로부터 자식 컴포넌트에게 state의 상태값, event handler를 넘겨 줄 수 있다.
부모에서 전달해준 데이터 타입 : 문자, 숫자, 함수... 모두가능
부모에서 전달해준 데이터 개수 : 여러개 전달도 가능!!!</p>
<h3 id="2-props-객체">2. Props 객체</h3>
<p>부모 컴포넌트로부터 전달 받은 데이터를 지니고 있는 객체</p>
<h3 id="3-props--event">3. Props &amp; Event</h3>
<p>this.props(객체)를 통해 특정 키에 접근한다.
키는 부모요소에서 만들어 둔 것을 받아온다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Merge VS Rebase
]]></title>
            <link>https://velog.io/@93_0312/Merge-VS-Rebase</link>
            <guid>https://velog.io/@93_0312/Merge-VS-Rebase</guid>
            <pubDate>Mon, 26 Jul 2021 00:54:01 GMT</pubDate>
            <description><![CDATA[<p>Merge VS Rebase</p>
<p>Git - MERGE
history가 중요한 경우 사용하는 명령어.
서로 다른 브랜치가 병합될 경우, 커밋 남긴 시점 사이사이에 들어와서 merge가 되고 merge commit이 맨 뒤로 온다.</p>
<p>Git - REBASE
깔끔한 이력 관리를 위한 명렁어.
베이스 커밋의 위치를 다시 잡는다. 한쪽에 있는 브랜치를 다른 브랜치에 병합하는 것. Rebase는 이력을 깔끔하게 정리할때 사용할 수 있는 장점이 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JSX 사용법]]></title>
            <link>https://velog.io/@93_0312/JSX-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
            <guid>https://velog.io/@93_0312/JSX-%EC%82%AC%EC%9A%A9%EB%B2%95</guid>
            <pubDate>Mon, 19 Jul 2021 01:04:55 GMT</pubDate>
            <description><![CDATA[<h3 id="jsx-사용법">JSX 사용법</h3>
<p>JS를 사용할 때 {}로 감싸준다.
class 가 아닌 className을 사용한다.(React class컴포넌트 탓인듯)
inline style을 사용할 때</p>
<pre><code>&lt;div style={{color : &quot;red&quot;}}&gt;Hello React&lt;/div&gt;</code></pre><h4 id="self-closing-태그">self closing 태그</h4>
<pre><code>&lt;div/&gt;</code></pre><p>모든 요소를 감싸는 최상위 요소
중요하다 태그를 사용할 때 부 요소들을 감싸는 최상위 요소가 있어야 한다. 태그가 생성되길 원치 않는다면 Fragments (&lt;&gt;&lt;/&gt;)를 사용할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프론트엔드 면접 준비]]></title>
            <link>https://velog.io/@93_0312/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%A9%B4%EC%A0%91-%EC%A4%80%EB%B9%84</link>
            <guid>https://velog.io/@93_0312/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EB%A9%B4%EC%A0%91-%EC%A4%80%EB%B9%84</guid>
            <pubDate>Mon, 19 Jul 2021 01:01:22 GMT</pubDate>
            <description><![CDATA[<p>단골 질문 - 기본적으로 다 알고 대답할 수 있어야 하는 내용
프런트엔드 개발자 면접이라면 거의 빠지지 않고 물어보는 내용입니다. 웹 서비스를 개발하기 위해서 기본적으로 알아야 하는 지식과 함께 빠르게 변화하는 프런트엔드 개발 생태계를 따라가기 위한 노력을 질문하였습니다.</p>
<p>브라우저 저장소에 대해서 설명해 보세요
ex) 로컬 스토리지, 세션 스토리지, 쿠키 각각 설명
ex) 로컬 스토리지와 쿠키의 차이점 설명
자바스크립트 this란?
ex) 화살표 함수, call, bind, apply 등
자바스크립트 이벤트 관리 방법? 보통 어떤 식으로 이벤트를 설계해야 하는지?
ex) 이벤트 캡처링 &amp; 버블링
ex) 이벤트 등록 &amp; 해제
ex) 이벤트 위임 방식 등
자바스크립트 비동기 처리에 대한 설명
ex) 콜백, 프로미스, async await
ex) 비동기 처리의 특성 및 에러 처리 방법?
프런트엔드 개발은 지속적으로 학습해야 하는 분야인데 어떤식으로 학습을 하고 있는지?
직무 관련 질문 - 최소 70% 이상 대답할 수 있으면 좋지 않을까? 하는 내용
프런트엔드 개발의 기술적인 부분뿐만 아니라 지원자의 전반적인 웹 서비스 개발 경험을 파악할 수 있는 질문입니다. 아래 질문에 전반적으로 고루 답변할 수 있는 분이라면 하나의 웹 서비스를 담당하실 수 있을 것이라 생각합니다.</p>
<p>프런트엔드 빌드 시스템에 대해서 설명해보세요.
바벨이란?
폴리필이란?
Node.js란?
NPM이란?
ESLint란?
Prettier란?
웹 태스크 매니저란?
웹팩이란? 모듈 번들러가 무엇인가요?
자바스크립트 프레임워크를 써봤는지? 써봤다면 어떤 걸 쓰는지? 만약 쓴다면 쓰는 이유와 썼을 때의 장점?
“기획 - 디자인 - API 개발 - 프런트엔드 개발”의 서비스 절차에서 프런트엔드 개발자의 역할은 무엇이라고 생각하는지?
CORS란? CORS를 해결하기 위한 방법을 아는 대로 모두 설명해 주시고 보통 어떤 방식으로 해결하는지 자주 사용하는 방법 1가지와 함께 실제 해결하신 경험을 공유해 주세요.
프런트엔드 성능 최적화란? 프런트엔드 성능 최적화 경험이 있다면 자세하게 설명해달라.
백엔드 개발 경험이 있는가?
(꼬리 질문) REST API 구축 경험과 구현 관점에서의 간단한 REST API 설계 방식 설명해 보세요. 브라우저의 URL 요청을 받아서 서버의 데이터를 화면에 다시 뿌려주기까지의 백엔드 쪽의 플로우를 알고 있는지 확인하는 차원.
Virtual DOM이 뭔지 아시는지? 썼을 때의 장점?
(꼬리 질문) 브라우저 동작 원리 아는 만큼 설명
웹 서비스 배포 시스템 구축 경험?
(꼬리 질문) CI, CD가 무엇인지 아는지? 구축해본 경험 혹은 사용해본 경험이 있는지
테스트 자동화 경험? 단위 테스트 또는 E2E 코드를 작성해 본적이 있는지?
(꼬리 질문) 테스팅 라이브러리와 프레임워크에 특화된 테스팅 라이브러리는 각각 어떤 걸 썼는지?
(꼬리 질문) 테스트 대상과 커버리지는 보통 어떻게 잡는지?
웹 접근성과 시맨틱 마크업이란? 이 2가지를 지키기 위해 보통 어떤식으로 마크업을 작성하는지?
웹 서비스를 기획부터 배포까지 모두 스스로 해본 경험이 있는가? 토이 프로젝트나 회사 서비스 등
(꼬리 질문) 구체적으로 어떤 역할을 수행했는지 설명
SEO(검색 엔진 최적화)란? 적용 사례가 있으면 구체적인 적용 방법도 같이 설명
REST API로 받은 객체와 배열은 보통 어떤 자바스크립트 API나 로직을 이용해서 화면에 맞게 가공을 하는지?
(꼬리 질문) map, filter, reduce API 사용 경험과 각각 설명
함수형 프로그래밍이란?
(꼬리 질문) 자바스크립트 클로저란?
(꼬리 질문) 자바스크립트 프로토타입이란?
서버 사이드 렌더링과 싱글 페이지 애플리케이션의 차이점?
(꼬리 질문) 서버 사이드 렌더링이나 SPA로 각각 구현해 본 경험이 있는지?
나올 수 있는 질문
그 외 물어볼만한 질문들 그리고 서비스와 조직 차원에서 이상적인 동료인지 힌트를 얻을 수 있는 질문입니다.</p>
<p>타입 시스템에 대해서 알고 있는지? 타입스크립트를 써봤는지?
(꼬리 질문) 자바스크립트와 타입스크립트의 차이점?
(꼬리 질문) 타입스크립트의 장점과 단점?
웹 서비스의 사용성을 개선하기 위해 고민해 봤던 부분이 있는지? 구체적인 사례와 경험 설명
자바스크립트 관련해서 모르는 문법이나 API가 나왔을 때 관련 정보를 어떻게 검색하는지?
다른 직무의 동료들과 어떤 식으로 커뮤니케이션 하는지?
여태까지 소속되었던 팀 내부적으로 혹은 회사 외부적으로 지식 공유나 지식 전파 같은 활동들을 해본 적이 있는지?
새로 배우는 개발 지식은 보통 어떤 식으로 정리하는가?
코딩 컨벤션은 보통 어떤 걸 따르고 코딩 컨벤션을 프로젝트에 적용하기 위해 어떤 노력들을 하는지?</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2진법 변환과 개수 카운팅]]></title>
            <link>https://velog.io/@93_0312/2%EC%A7%84%EB%B2%95-%EB%B3%80%ED%99%98%EA%B3%BC-0%EC%9D%98%EA%B0%9C%EC%88%98</link>
            <guid>https://velog.io/@93_0312/2%EC%A7%84%EB%B2%95-%EB%B3%80%ED%99%98%EA%B3%BC-0%EC%9D%98%EA%B0%9C%EC%88%98</guid>
            <pubDate>Mon, 12 Jul 2021 15:20:01 GMT</pubDate>
            <description><![CDATA[<p>위코드를 다니며, 다짐했던 것 중 매일마다 돌아오는 코드카타시간을 지킨다는 것이 있었다. 하지만 오늘 1차프로젝트의 중간발표 및, 그동안 해오지 못한 코드정리, 리뷰, 멘토님들과의 미팅을 보내다보니 코드카타를 까먹고 아예 켜보지도 못해, 집에 들어오자마자 문제를 풀고 블로그에 남기게 되었다. 앞으로도 문제를 해결하지 못하더라도 반드시 코드카타 시간을 지켜나가고 싶다.</p>
<p><img src="https://images.velog.io/images/93_0312/post/e7c7248f-6da4-486a-b666-8288d5b1a831/image.png" alt=""></p>
<p>코드테스트 기초문제를 풀다보면, 무언가의 사이에 있는 무언가의 개수를 세는 이런 형태의 사고방식이 종종 등장하는 것 같다.
<img src="https://images.velog.io/images/93_0312/post/3560f5c7-c01b-473e-94eb-9a69d6049866/image.png" alt=""></p>
<p>1사이에 0을 세는 문제로, 언젠지 기억은 안나지만 예전에 어떤 문제를 풀면서 생각했었고, 다른 동기들의 코드를 보며 기억해 두었던 최대값을 저장하는 변수, 카운팅을 해주는 변수 두개를 이용해 문제를 쉽게 풀 수 있었다. </p>
<p>이런형태의 코딩? 사고방식?은 기억해 둔다면 다른 상황에서도 유용하게 사용될 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[RESTful API]]></title>
            <link>https://velog.io/@93_0312/RESTful-API</link>
            <guid>https://velog.io/@93_0312/RESTful-API</guid>
            <pubDate>Sun, 11 Jul 2021 12:06:33 GMT</pubDate>
            <description><![CDATA[<h3 id="restful-apiapplication-program-interface">RESTful API(Application Program Interface)</h3>
<p>API 시스템을 구현하기 위한 아키텍처 중에 가장 널리 사용되는 형식</p>
<h4 id="restful-api는-그-자체만으로도-api의-목적이-쉽게-이해가-된다">RESTful API는 그 자체만으로도 API의 목적이 쉽게 이해가 된다.</h4>
<p>RESTful API 설계 규칙
URI 정보를 명확하게 표시한다. resouce는 명사를 사용한다.
ex)GET/user/1 -&gt; GET/users/1
resouce에 대한 행위를 HTTP Method(GET, POST, PUT, DELETE)로 표현한다.
URI에 HTTP Method가 포함되서는 안된다.
ex)GET delete/user/1 -&gt; DELETE/users/1
URI에 동사가 포함되서는 안된다.</p>
<p>RESTful API를 사용하면 데이터통신을 하는데 있어 원하는 것을 명확하게 표시해 줄 수 있고, 원하는 데이터만 받아올 수 있는 등의 장점이 있어, 널리 쓰이고 있는 API 설계방식이라고 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[고기각 프로젝트]]></title>
            <link>https://velog.io/@93_0312/%EA%B3%A0%EA%B8%B0%EA%B0%81-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</link>
            <guid>https://velog.io/@93_0312/%EA%B3%A0%EA%B8%B0%EA%B0%81-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8</guid>
            <pubDate>Sun, 11 Jul 2021 12:02:54 GMT</pubDate>
            <description><![CDATA[<p>위코드에 들어와서 처음으로 고기각 프로젝트를 진행하고있다.
모든일에서 그렇듯 서로의 생각을 말을 하지 않으면 서로가 어떤 생각인지 알 수 없기 때문에, 서로서로 필요한 점을 얘기하고 정확히 소통하는 것이 정말 중요한 것 같다.</p>
<p>프론트엔드와 백엔드 서로 사용하는 언어가 많이 다르기 때문에, 처음에는 이야기 하는데에 있어서 장애가 되는 부분도 많이 있었지만, 다행히 좋은 팀원분들 덕에 이제는 어느 다른조보다도 화목한? 팀이지 않나 생각이 들정도로 프로젝트가 잘 진행되고 있어서 좋은 것 같다. 어쩌면 조금 어려운 함수 / 기능을 구현하는 것 보다도, 팀원들과 서로서로 소통하는법을 배워가는 과정이 1차프로젝트의 핵심이 아닐까? 생각해본다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[props.history]]></title>
            <link>https://velog.io/@93_0312/props.history</link>
            <guid>https://velog.io/@93_0312/props.history</guid>
            <pubDate>Sun, 11 Jul 2021 11:59:54 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/93_0312/post/7decdda8-94cf-4299-8e52-b3dd6f04b16d/image.png" alt=""></p>
<p>라우터에 직접적으로 명시된 컴포넌트는 props에 history객체를 받아서 주소를 변경해주는 함수를 사용할 수 있다.</p>
<p>라우터에 직접 명시되지 않은 컴포넌트에서 history 객체를 사용하고 싶다면 withRouter를 사용해 주어야한다.</p>
<p>동적라우팅을 하기위해서 패스파라미터를 사용해야 할 때가 있기 때문에, 알아두면 좋은 개념인것 같다. 동적라우팅 세션은 화요일에 하게 되는데, 헷갈리는 개념이기 때문에 다시한번 정리하는느낌으로 세션을 열심히 들어야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[위코드에서의 한 달]]></title>
            <link>https://velog.io/@93_0312/%EC%9C%84%EC%BD%94%EB%93%9C%EC%97%90%EC%84%9C%EC%9D%98-%ED%95%9C-%EB%8B%AC</link>
            <guid>https://velog.io/@93_0312/%EC%9C%84%EC%BD%94%EB%93%9C%EC%97%90%EC%84%9C%EC%9D%98-%ED%95%9C-%EB%8B%AC</guid>
            <pubDate>Sun, 04 Jul 2021 07:14:58 GMT</pubDate>
            <description><![CDATA[<h3 id="위코드-한-달-">위코드 한 달 ,</h3>
<p>&amp;nbsp
&amp;nbsp</p>
<h4 id="동기들과-함께-하는-것">동기들과 함께 하는 것</h4>
<p>&amp;nbsp
&amp;nbsp&amp;nbsp 서른 명 남짓의 동기들이 각자의 사연을 가지고 위코드에 모였다고 생각한다.
그렇기에 그 중, 코딩을 남들보다 잘하시는 분들, 들어는 보신 분, 한 번도 해보지 않았지만, 어떠한 이유로 인해 시작하게 된 분들도 있겠지,,</p>
<p> &amp;nbsp혼자 공부하는 것보다, 프론트엔드 / 백엔드 개발자라는 동일한 목표를 향해서 함께 공부해나가는 것이 은연중에 모두에게 동기부여가 되어, 좋은 영향을 끼치고 있다고 생각하고 있고, 이것은 비단 위코드가 아니어도 함께 공부해나가는 모든 부트캠프의 장점인 것 같다.</p>
<p>&amp;nbsp&amp;nbsp또한 지금 잘하고 못하고는 중요하지 않다고 생각한다. 알면 아는 대로, 모르면 모르는 대로 새로 배워나갈 내용은 끝없이 남아있고, 지금 남들보다 조금 더 안다고 해서 일 년 뒤, 그 위치가 역전당하지 않을 거라는 보장은 없다고 생각한다. 그렇기에 모두가 모여서 열심히 공부하는 것은 모두에게 의미가 있는 일인 것 같다.</p>
<p>&amp;nbsp
&amp;nbsp</p>
<h4 id="1차-프로젝트를-앞둔-내-기대">1차 프로젝트를 앞둔 내 기대,</h4>
<p>&amp;nbsp
&amp;nbsp&amp;nbsp다른 부트캠프에 대해서는 잘 알지 못하지만, 1차 2차 프로젝트, 그에 이어지는 기업협업이라는 부분이 위코드의 장점이라고 생각한다. 개발자를 목표로 하는 분들을 5~6명 모아 하나의 프로젝트를 해 나아가는 경험은, 위코드에 다니지 않는다면 하기 힘들 것이라고 생각한다. 프로젝트를 진행하며 많은 실패와 성공을 반복하며 최대한 많은 것들을 경험하고 싶다.</p>
<p>&amp;nbsp
&amp;nbsp</p>
<h4 id="한-달-마무리">한 달 마무리</h4>
<p>&amp;nbsp
&amp;nbsp&amp;nbsp 개발자로의 커리어를 위해, 나를 포함한 많은 분들이 적지 않은 수강료를 내고 위코드를 다니게 되었다고 생각한다. 하지만 아쉽게도 위코드를 비롯한 모든 코딩부트캠프는 가만히 있는? 이들을 마법같이 개발자로 변신시켜주는 곳이 아니다.</p>
<p>&amp;nbsp&amp;nbsp 모든 배움이 그렇듯이, 공부해 나아가다 보면, 모르는 것, 부족한 부분이 생기게 된다. 이때, 함께 공부하는 주변 사람들, 또는 멘토님들께 물어볼 수 있다는 것이 위코드의 장점이 아닐까? 모르는 것들을 하나하나 알아가다 보면, 지금은 너무나 멀어 보이는 개발자라는 목표에 도달할 수 있지 않을까? 생각이 든다.</p>
<p>&amp;nbsp
&amp;nbsp
&amp;nbsp
&amp;nbsp
&amp;nbsp
&amp;nbsp</p>
<h4 id="ps">P.S.</h4>
<p>모른다는 것은 절대로 부끄러운 일이 아니라고 생각한다. 모른다는 것을 인정하고, 알아나가는 사람은 계속해서 발전하지만, 어느 순간 자신이 모른다는 것을 부정하는 사람은 더는 발전해 나갈 수 없다고 생각하기 때문이다. 화이팅</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[this.setState()]]></title>
            <link>https://velog.io/@93_0312/this.setState</link>
            <guid>https://velog.io/@93_0312/this.setState</guid>
            <pubDate>Thu, 01 Jul 2021 06:58:07 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/93_0312/post/64f4c607-d1cc-46b7-8fc0-15cffb8af781/image.png" alt=""></p>
<p>이런 형태의 목데이터가 있을때, 배열안의 각 객체가 각각 하나의 피드를 이루게 된다.</p>
<p><img src="https://images.velog.io/images/93_0312/post/716b6909-1bae-4c73-9bd8-a16529d8dfcc/image.png" alt=""></p>
<p>목데이터는 feeds라는 스테이트에 저장됨.</p>
<p>목데이터를 활용한 피드가 10개정도 있다고 했을 때, 5번째 피드에 댓글이 추가되거나, 삭제, 좋아요 버튼 등을 눌렀다고 한다면 어떻게 처리해야 하는가?</p>
<p>스테이트를 다루는 방식에 대해 하나도 이해하지 못했을 때, 나는 this.setState({feeds[0].replies: ..... } 처럼 이제보면 말같지도 않은 방식을 떠올렸고, 그러한 방식을 통해 해당 기능을 구현하려고 몇시간동안 에러메세지만 보기도 했다.</p>
<p>이를 해결하기 위해서,</p>
<p><img src="https://images.velog.io/images/93_0312/post/9d84d0b8-d301-4b99-a98a-06fbf1058b69/image.png" alt=""></p>
<p>이런 방식을 선택했다. 스테이트가 전부 복사된 newFeeds를 만들고, 해당 객체를 먼저 바꿔준 뒤, 이를 feeds에 통으로 setState 해주는 방식, 삭제와 좋아요도 비슷한 원리를 이용해서 해결할 수 있었다.</p>
<p>setState()함수는 state에 저장된 값을 변경해주는 것이기 때문에, state에 명시되지 않은 부분에 대해서는 변경할 수 없는? 것 같다</p>
<p>리액트에서 나름 중요해 보이는 setState()에 대해서 배웠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[첫 HTTP 통신 테스트]]></title>
            <link>https://velog.io/@93_0312/%EC%B2%AB-HTTP-%ED%86%B5%EC%8B%A0-%ED%85%8C%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@93_0312/%EC%B2%AB-HTTP-%ED%86%B5%EC%8B%A0-%ED%85%8C%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Thu, 01 Jul 2021 06:48:58 GMT</pubDate>
            <description><![CDATA[<p>클론 프로젝트를 하면서, HTTP통신은 이용하지 않고 목데이터를 사용해서 클론을 진행하고 있었는데, 드디어 HTTP통신을 시도해 보았다.</p>
<p>첫 통신의 흔적</p>
<p><img src="https://images.velog.io/images/93_0312/post/8a07d25e-e9cf-43fc-9fac-d3f5d6ed6b49/image.png" alt=""></p>
<p>로그인페이지라고 만들어 두었던 곳의 두칸의 인풋, 버튼하나를 이용해서 회원가입, 로그인을 진행하고 급하게 만든 포스팅 버튼을 이용해서 이미지를 실제 데이터에 추가하기도하고, 이를 통해 추가된 이미지를 이용해서 피드형식으로 디스플레이 하기도 했다.</p>
<p>사전에 미리 협의된 점이 하나도 없었지만, 첫 테스트에서는 의외로 통신이 잘 이루어져서 신기하고 재밌었다.</p>
<p>토큰을 로컬스토리지에 저장하는 부분, 이 토큰을 다시 재사용해 내가 누구인지 증명하면서 데이터를 추가하는 작업이 가장 신기했던 것 같음.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[코드카타 5]]></title>
            <link>https://velog.io/@93_0312/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-5</link>
            <guid>https://velog.io/@93_0312/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-5</guid>
            <pubDate>Fri, 25 Jun 2021 11:37:14 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/93_0312/post/a6ab607e-c98f-4932-8847-55640ca2e8fa/image.png" alt=""></p>
<p>공통된 시작단어를 반환하는 문제였다.</p>
<p><img src="https://images.velog.io/images/93_0312/post/97af5b51-2904-4271-8084-634164a10faa/image.png" alt=""></p>
<p>비교를 위해 checkStr하나를 선언해준뒤, </p>
<p>입력된 strs가 비어있는 값이 아니면 checkStr에 저장,
비어있을 경우 공통된 시작단어는 당연히 없으므로 &quot;&quot;를 리턴해준다.</p>
<p><img src="https://images.velog.io/images/93_0312/post/4841bb9c-5446-4848-8d2a-aba1ac4a0219/image.png" alt=""></p>
<p>변수명이 뭔가 이상해보이지만,,, 같은 글자의 위치?인덱스를 -1로 초기설정해준다.
0이 아닌 -1인 이유는 String에서 0번이 맨 앞을 뜻하기 때문이다.
strs에 들어있는 요소들의 첫글자가 모두 다른지 같은지 모르기 때문에, 일단 -1번을 넣어 주었다.</p>
<p>이후, 포문을 strs의 첫번째요소의 length만큼 돌려주며..</p>
<p>strs에 filter메소드를 사용해준다. i+1번째 글자가 같은 배열의 요소들로만 이루어진 배열이 반환되며 checkStr에 할당된다.</p>
<p>동시에 글자의 위치를 나타내는 sameCharindex에 1을 더해준다.</p>
<p><img src="https://images.velog.io/images/93_0312/post/c1df3c9b-0625-4647-aa10-328a9c0f0d48/image.png" alt=""></p>
<p>포문이 종료 된 이후, 구해진 sameCharindex를 이용해 string메서드인 substring 메서드를 이용한다. </p>
<p>.substring(0,3)의 경우 첫번째 두번째 세번째 글자까지 나오게 된다. 위쪽의 for문이 돌아가면서 마지막 if문이 실행되었을 때 sameCharindex은 여전히 + 되므로 그대로 사용하면 sameLetter을 구할 수 있다.</p>
<p><img src="https://images.velog.io/images/93_0312/post/52c21526-0e84-4552-b927-abe338df78b7/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[코드카타 1 (indexOf())]]></title>
            <link>https://velog.io/@93_0312/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-1-indexOf</link>
            <guid>https://velog.io/@93_0312/%EC%BD%94%EB%93%9C%EC%B9%B4%ED%83%80-1-indexOf</guid>
            <pubDate>Fri, 25 Jun 2021 01:02:10 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/93_0312/post/fe2929b9-39ec-4b2b-a720-b4b147510648/image.png" alt=""></p>
<p>문제를 보고 바로 떠오른생각</p>
<ol>
<li>이중포문을 사용해서 전부 더해서 비교해준다.</li>
<li>1번에 이어서 포문을 하나만 사용할 수는 없는지에 대한 생각이 들었고, nums[i]+nums[j]=target이라는 식을 통해 역으로 이미 정해져있는 target을 이용 target-nums[i]=nums[j]를 푸는것으로 정했다.</li>
<li>nums[i]+nums[j] = target을 만족하는 조건에서만 해당함수가 작동하면 되기에, 애초에 nums배열에서 target보다 큰 수는 제외해주는 방식이 좋겠다고 생각하게 되었다. -&gt; 예시의 배열은 4개를 갖고 있지만, 만약 nums배열이 100만개정도 있다고 가정한다면 for문을 전부 돌리는 것도 낭비이며, target이 충분히 작을때, target보다 큰 수를 제외하고 함수를 작동시키면 의미있는 차이가 있을 것이라고 생각했다.</li>
</ol>
<p>나의 풀이</p>
<p>array.filter(x&lt;target) 을 이용해 nums배열에서 target보다 작은 요소만 남긴다.</p>
<p>indexOf(target-nums[i])가 -1이 아닌 배열의 위치를 찾아서,
return (i,indexOf(target-nums[i])를 해준다.</p>
<p>완성</p>
]]></description>
        </item>
    </channel>
</rss>