<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ys_sung.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Fri, 12 Apr 2024 13:34:37 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ys_sung.log</title>
            <url>https://velog.velcdn.com/images/ys_sung/profile/ce0049fb-3c50-4cdc-8bde-16bd1ab4e6d0/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ys_sung.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ys_sung" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[프로그래머스 '기능개발' 풀이]]></title>
            <link>https://velog.io/@ys_sung/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EA%B8%B0%EB%8A%A5%EA%B5%AC%ED%98%84-%ED%92%80%EC%9D%B4</link>
            <guid>https://velog.io/@ys_sung/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EA%B8%B0%EB%8A%A5%EA%B5%AC%ED%98%84-%ED%92%80%EC%9D%B4</guid>
            <pubDate>Fri, 12 Apr 2024 13:34:37 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-js">// solution :: Array&lt;number&gt; -&gt; Array&lt;number&gt; -&gt; Array&lt;number&gt;
// TODO: 시간복잡도 개선
// TODO: 명령형으로 작성된 코드를 함수형으로 개선 √
// TODO: 스택 활용하여 구현
// TODO: 다른 사람들 풀이 보고 숙지

// - 콜스택을 활용한 함수형(?) 구현
// - 속도는 이 구현이 오히려 더 느리다.
function solution(progresses, speeds) {
    // getSpeedsFromProgresses :: Array&lt;number&gt; -&gt; Array&lt;number&gt; -&gt; Array&lt;number&gt;
    const getSpeedsFromProgresses = (progresses, speeds) =&gt; {
        return speeds.slice(-progresses.length);
    }

    // sumCount :: Array&lt;number&gt; -&gt; number -&gt; [number, Array&lt;number&gt;]
    const sumCompletedFeature = (progresses, count = 0) =&gt; {
        if (progresses.length === 0) return [count, progresses];
        if (progresses[0] &gt;= 100) return sumCompletedFeature(progresses.slice(1), count + 1);
        else return [count, progresses];
    }

    // recur :: Array&lt;number&gt; -&gt; Array&lt;number&gt; -&gt; Array&lt;number&gt;
      return (function recur(progresses, speeds, result = []) {
        if (progresses.length === 0) return result;

        const progressesInADay = progresses.map((progress, idx) =&gt; progress + speeds[idx]);
        const [currentSum, currentProgresses] = sumCompletedFeature(progressesInADay);
        const currentResult = currentSum === 0 ? result : [...result, currentSum];

        return recur(
            currentProgresses,
            getSpeedsFromProgresses(currentProgresses, speeds),
            currentResult
        );
    })(progresses, speeds);
};

/* - 명령형 구현
function solution(progresses, speeds) {
    var answer = [];

    while (speeds.length &gt; 0) {
      progresses.forEach((progress, idx) =&gt; {
          progresses[idx] = progress + speeds[idx];
      });


      let count = 0;
      while (progresses[0] &gt;= 100) {
          progresses.shift();
          speeds.shift();
          count += 1;
      }

      if (count &gt; 0) answer.push(count);
    }

    return answer;
}
*/</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[cleanList 개발기 - 청소메뉴(설문, 투두리스트)]]></title>
            <link>https://velog.io/@ys_sung/cleanList-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EA%B5%AC%ED%98%84%EC%84%A4%EB%AC%B8-%ED%88%AC%EB%91%90%EB%A6%AC%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@ys_sung/cleanList-%EA%B0%9C%EB%B0%9C%EA%B8%B0-%EA%B5%AC%ED%98%84%EC%84%A4%EB%AC%B8-%ED%88%AC%EB%91%90%EB%A6%AC%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Sun, 26 Mar 2023 10:58:15 GMT</pubDate>
            <description><![CDATA[<h3 id="기능-리스트">기능 리스트</h3>
<ul>
<li><p>청소메뉴</p>
<ul>
<li><input checked="" disabled="" type="checkbox"> 설문</li>
<li><input checked="" disabled="" type="checkbox"> 투두리스트</li>
</ul>
</li>
<li><p>도면메뉴</p>
<ul>
<li><input disabled="" type="checkbox"> 새로운 영역 추가</li>
<li><input disabled="" type="checkbox"> 청소기록에 따른 배경색 변화</li>
</ul>
</li>
</ul>
<hr>
<p> 열심히 기획을 하긴 했는데 어디서부터 코딩을 시작해야할지 좀 막막했다. 생각나는 페이지부터 만드는 게 내가 항상 하던 일이지만 이번에는 뭔가 체계적으로 해보고 싶었다.</p>
<p> 리액트 공식문서에 <a href="https://react.dev/learn/thinking-in-react">thinking in react</a>이라는 문서가 있는데 리액트 앱을 설계하는 단계를 설명하고 있는 문서다. 이 문서에 따르면 컴포넌트를 만들고 상태를 설정하는 과정을 5단계로 설명하고 있는데 그 단계는 다음과 같다.</p>
<ol>
<li><p>컴포넌트 계층구조 설계</p>
</li>
<li><p>(상태가 없는) 정적인 버전의 어플리케이션 만들기</p>
</li>
<li><p>앱에서 필요한 상태들이 무엇인지 파악하기</p>
</li>
<li><p>각 상태들이 어느 컴포넌트에 있어야하는지 결정하기</p>
</li>
<li><p>역방향 데이터설계 추가하기(ex-state를 변경하는 함수를 props로 하위 컴포넌트에 넘겨주기)</p>
<p>하지만 이 단계를 정확하게 따르는 데는 실패하고 말았다. 컴포넌트 계층구조를 생각하는 도중에 어떤 상태가 필요한지 떠오르고 그 작업으로 넘어갔다가 다시 돌아오곤 했던 것이다. </p>
<p>다음에는 작업 단위를 더 잘게 쪼개고 현재 작업하지 않는 것과 같은 아이디어는 메모해두고 나중에 해야겠다고 생각했다</p>
</li>
</ol>
<h2 id="기능1-질문에-대답을-받아서-리덕스-스토어에-저장설문페이지">기능1: 질문에 대답을 받아서 리덕스 스토어에 저장(설문페이지)</h2>
<p>  먼저 기획단계에서 정리한 질문들의 타입을 정의했다. 
    1. 질문들을 후속 질문들을 결정하는 타입의 질문<em>(타입1: 사전질문. 형식상으로는 &#39;다중일택&#39; 질문</em>)과 특정 청소를 추가할 것인지를 묻는 질문(<em>타입2: 청소선택질문. 형식상으로 &#39;양자택일&#39; 질문</em>)으로 분류한다.
    2. 질문들은 공통적으로 (난이도 | 질문이 속한 영역 | 질문텍스트(ex-&#39;바닥 청소를 하실건가요?&#39;)) 값을 갖고 있고 이 중에 난이도와 영역을 결정하는 질문으로 질문들을 필터링한다
    3. 타입1의 질문들은 string 타입의 값을 답으로 받아서 그에 따라 후속 질문들을 필터링하고, 타입2의 질문들은 boolean 타입의 값을 답으로 받아서 그 값에 따라 매핑된 청소가 추가될지 아닐지 판단했다. </p>
<p>   <img src="https://velog.velcdn.com/images/ys_sung/post/a6abf054-b785-4a01-8a00-b9330cdce81c/image.png" alt="청소 타입정리"><em>지금까지 혼자서 프로젝트를 하면서 자바스크립트를 사용했었는데 이번에 타입정의를 해보면서 구현이 좀 더 명료하게 정리되는 경험을 하였다.</em></p>
<h3 id="설문페이지-로직">설문페이지 로직</h3>
<p><img src="https://velog.velcdn.com/images/ys_sung/post/f5aa67ad-de17-4d04-a20c-c4ac3c65bda3/image.jpeg" alt="">
이런 타입을 기반으로 작성한 설문페이지의 로직은 다음과 같다.</p>
<ol>
<li>질문들은 사전질문과 본질문으로 나뉘고 본질문은 또 영역으로 구분하여 (공통 | 침실 | 욕실 | 주방 | 베란다)로 나누었다.</li>
<li>사전질문의 대답은 문자열로 받아서 그 값과 같은 질문들을 필터링한다. (ex - 어떤 영역을 청소할 것인가에 대한 질문에 침실이라고 대답하면 침실관련 질문만 필터링)</li>
<li>(사전질문에 의해서 1차로 필터링된) 본질문들에  답변을 받고 답변을 저장해서 true인 청소들을 필터링한다.</li>
<li>생성된 청소배열을 redux store에 저장하고 투두리스트 페이지로 라우팅한다.</li>
</ol>
<h2 id="기능2-유저의-대답에-따른-청소-투두리스트-생성">기능2: 유저의 대답에 따른 청소 투두리스트 생성</h2>
<p>투두리스트에서 구현해야 하는 기능은 다음과 같다.</p>
<h4 id="1-페이지-최초-렌더링시-store에-청소데이터-배열에-값이-있으면-렌더링">1. 페이지 최초 렌더링시 store에 청소데이터 배열에 값이 있으면 렌더링</h4>
<p>리덕스에 있는 값이 있으면 리스트를 렌더링하고 아니면 설문 페이지로 라우팅하면 간단하게 구현된다. 렌더링하는 김에 css 스타일링, 트랜지션 애니메이션으로 꾸며주었다.</p>
<h4 id="2-하나의-청소를-완료처리하거나-삭제하면-store에-반영">2. 하나의 청소를 완료처리하거나 삭제하면 store에 반영</h4>
<p>청소의 체크상태를 토글하는 리듀서와 삭제할 타겟을 제외하는 리듀서를 작성했다. </p>
<p>현재 청소데이터는 store에만 담겨있지만, 나중에는 db의 값과 연동할때 문제가 될 것 같았다. 완료처리, 삭제(그리고 3번의 순서변경)은 사용자가 자주 사용하는 기능이라서 쓸데없는 네트워크 통신이 많아질 것이기 때문이다. 왠만하면 스토어에만 저장해두고 싶었는데메모리에 있는 값들은 브라우저를 새로고침하면 모두 소실되어 버리는 문제가 있었다.</p>
<p>그래서 고민하다가 <a href="https://www.npmjs.com/package/redux-persist">redux-persist</a>라는 라이브러리가 있다는 걸 알게 되었다. 이 라이브러리는 localStorage와 리덕스 store를 연동해주는 편리한 라이브러리이다. 로그아웃해서 청소리스트를 지워주기로 하고 그 전에는 리스트를 계속 유지하기로 하였다.</p>
<p><img src="https://velog.velcdn.com/images/ys_sung/post/664a96a9-a2c4-4ebc-b77f-f9b75b98f087/image.jpeg" alt=""><em>이렇게 하니 청소리스트에서 체크를 하다 다른 메뉴에 이동했다가 다시 돌아와도 진행상태를 계속 유지할 수 있어서 좋았다.</em></p>
<h4 id="3-드래그로-순서변경하면-store에-반영">3. 드래그로 순서변경하면 store에 반영</h4>
<p><img src="https://velog.velcdn.com/images/ys_sung/post/0951d60a-b78e-42ef-a206-c4be3391fee6/image.gif" alt="">
드래깅 라이브러리는 <a href="https://dndkit.com/">dnd kit</a>을 사용하였다. 공식 홈페이지에는 카드게임같은 예제가 있을 정도로 유려한 기능들이 많았다. 내가 필요한것은 리스트의 순서변경, 그 과정에서 필요한 애니메이션 같은 비교적 간단한 기능들이었고 이를 위한 api들이 있어서 요긴하게 사용했다. 배열의 순서를 바꾸는 로직도 내가 작성할 필요없이 함수를 제공해줘서 직접 구현하는 것보다 쉽게 만들 수 있었다.</p>
<h4 id="4-청소-진행률을-ui로-표시">4. 청소 진행률을 ui로 표시</h4>
<p>tailwindCSS 기반의 컴포넌트 라이브러리 daisyUI의 <a href="https://daisyui.com/components/radial-progress/">Radial progress
</a> 컴포넌트를 사용해서 청소 투두리스트의 진행률을 표시했다. 리액트는 컴포넌트가 언마운트될때 애니메이션을 주는 것이 번거로운데 Radial progress 컴포넌트에 <a href="https://www.react-spring.dev/">react-spring</a>의 도움을 받아서 값이 변할때 트랜지션도 적용해주었다.</p>
<h2 id="청소메뉴-구현을-마치며">청소메뉴 구현을 마치며</h2>
<p> 아이디어를 떠올리고 플로우차트와 와이어프레임을 만들면서 구현로직이 떠오르는 경우가 있었기 때문에 바로 코딩을 시작하는 것보다는 빠르게 처리할 수 있었던 것 같다. 예전에 사수분께서 코딩 하기 전에 생각을 많이 하는 것이 중요하다고 하셨는데 다시 한번 체감할 수 있었다. </p>
<p>(<em>계속됩니다!</em>)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[cleanList 개발기 - 기획]]></title>
            <link>https://velog.io/@ys_sung/%ED%8F%AC%ED%8A%B8%ED%8F%B4%EB%A6%AC%EC%98%A4-%ED%9A%8C%EA%B3%A0-1.-%EA%B8%B0%ED%9A%8D</link>
            <guid>https://velog.io/@ys_sung/%ED%8F%AC%ED%8A%B8%ED%8F%B4%EB%A6%AC%EC%98%A4-%ED%9A%8C%EA%B3%A0-1.-%EA%B8%B0%ED%9A%8D</guid>
            <pubDate>Tue, 14 Mar 2023 12:13:59 GMT</pubDate>
            <description><![CDATA[<p>이직을 하려고 인강들을 들으면서 React, Typescript 등을 학습했다. 강의 내에서도 실습 프로젝트가 있었지만 직접 프로젝트를 만들고 싶은 생각이 들었다. 포트폴리오 소재에 대해서 고민하던 중 회사에 재직하던 때 사수분께서 말씀하신 내 &#39;주변에서 해결해야할 문제&#39;가 무엇인지 먼저 찾아보라는 조언이 떠올랐다. 어떤 문제가 있을까 고민하다가 지저분한 내 방을 발견했다. 나는 청소를 무척 귀찮아했기 때문에 방도 지저분한 상태였다.</p>
<blockquote>
</blockquote>
<p> 청소하기 너무 싫다..</p>
<p> 그래서 떠올린 것이 &quot;게으름뱅이를 위한 청소 투두리스트&quot;이다.</p>
<h3 id="발상">발상</h3>
<p>보통 투두리스트를 사용하는 이유는 &quot;어떤일을 해야할지 생각하는 것&quot;과 &quot;실제로 그 일을 수행하는 과정&quot;을 분리하는 게 더 수월하다는 느낌 때문이라고 생각한다. 내 경우에는 정돈되어있는 투두리스트를 보면 (착각일지언정) 이미 할일을 다 끝낸 것 같은 성취감이 들때도 있었다.</p>
<p>그런데 여기서 &quot;어떤일을 해야할지 생각하는 것&quot;도 더 쉽게할 수 있으면 어떨까라는 아이디어가 떠올랐다. 청소를 항상 하면서도 체계없이 한다는 느낌이 많이들었고 그것에 대해 고민하는 것이 피곤하기도 했는데, 여러가지 질문에 대답하기만하면 잘 짜여진 투두리스트가 생성된다면 하기 싫은 청소도 좀 덜 싫어지지 않을까?</p>
<h3 id="기능1-청소-투두리스트">기능1: 청소 투두리스트</h3>
<p>먼저 &lt;유저에게 설문을 받아서 투두리스트를 생성&gt;한다는 아이디어를 구체적으로 생각해보았다.</p>
<ul>
<li>주방, 거실, 욕실 별로 필요한 청소들의 리스트를 뽑는다.(<a href="https://velog.io/@ys_sung/%EC%B2%AD%EC%86%8C-%EC%9E%91%EC%97%85-%EB%AA%A9%EB%A1%9D">청소태스크 리스트</a>)</li>
<li>각 청소 태스크는 디폴트 여부와 우선순위, 난이도 등의 값들을 가지고 있다.</li>
<li>먼저 디폴트인 청소들만 우선순위별로 리스트를 만든다.</li>
<li>질문을 통해서 특정 청소를 리스트에 끼워넣거나 제거하거나 한다.(<a href="https://velog.io/@ys_sung/%EC%B2%AD%EC%86%8C-%EC%B2%B4%ED%81%AC%EB%A6%AC%EC%8A%A4%ED%8A%B8">질문 리스트</a>)</li>
<li>만약 우선순위가 같은 값이 있다면 어떻게 정렬할지 유저에게 물어본다.</li>
<li>이 과정을 거쳐 최종적인 &quot;청소 투두리스트&quot;를 생성한다.</li>
</ul>
<h3 id="기능2-도면">기능2: 도면</h3>
<p>친구에게 기본 아이디어를 설명했더니 방의 대략적인 도면을 확인해서 특정 구역(ex: 거실, 욕실, 주방 등)의 청소를 언제쯤 실시했는지 확인하는 기능이 있으면 좋을 것 같다고 말해주었다. 좋은 아이디어인 것 같아서 해당 기능도 구현하기로 했다.</p>
<ul>
<li>청소 투두리스트를 생성할때 어느 구역을 청소할 것인지를 물어보는 질문을 넣는다.</li>
<li>선택한 구역에서 이미 생성된 것이 없다면 구역을 생성하는 과정으로 넘어가서 구역을 만든다.</li>
<li>도면 메뉴에서 청소를 한 지 오래된 구역일수록 배경색이 빨갛게 변한다.</li>
</ul>
<h3 id="대략적인-기능-그룹들">대략적인 기능 그룹들</h3>
<p>위의 내용들에 따라서 생각한 기능들의 그룹들을 생각해보았다. 추가적인 아이디어가 몇가지 있었지만 추린 후에 만든 &quot;반드시 있어야 하는 기능들&quot;의 목록이다.</p>
<ol>
<li>유저의 대답에 따라 커스텀된 청소투두리스트 생성 기능</li>
<li>특정 구역에 청소를 언제했는지 직관적으로 확인할 수 있는 도면생성/수정 기능</li>
<li>로그인, 로그아웃 등의 앱의 기본기능</li>
</ol>
<h3 id="플로우차트">플로우차트</h3>
<ul>
<li>mermaid를 사용해서 플로우차트를 그렸다.</li>
<li>도면 생성하는 단계를 어디에 추가해야하는지를 더 명확하게 결정하는 데 집중해서 그렸다.</li>
<li>도면 메뉴에서도 구역을 생성할 수 있게 해야한다는 것을 알 수 있었다.</li>
<li>&#39;체험해보기&#39;부분은 로그인없이 어떤 기능을 제공하는지 알 수 있게 하기 위함인데 일단 추가적인 구현사항으로 정해두기로 하였다.<img src="https://velog.velcdn.com/images/ys_sung/post/cf15968d-2b2c-4bed-b4b6-1584352a3be1/image.png" alt=""></li>
</ul>
<h3 id="와이어프레임">와이어프레임</h3>
<ul>
<li>카카오 오븐을 사용해서 작성한 플로우차트를 기반으로 와이어프레임을 만들었다.(<a href="https://ovenapp.io/view/7bj7EJk2wwMtGKylp1HG6dI4WdhBYQkJ/hNfud">카카오오븐 링크</a>)</li>
<li>작업을 하다보니 배경색 등의 스타일등도 추가했는데 촌스러워 보였다. 어쩔 수 없는 부분이라 생각하고 material ui나 daisyUI 같은 디자인시스템을 활용해서 조금이라도 개선해야겠다고 생각했다.</li>
<li>UI/UX에 대해서 더 많은 공부가 필요하다고 느꼈다.</li>
<li>대략적인 레이아웃의 틀을 잡았다. 당초 계획은 데스크톱버전도 생각했었는데 나중에 추가하는 것으로 변경하였다.</li>
</ul>
<h3 id="마지막으로">마지막으로..</h3>
<p>이 프로젝트를 구현해나가면서 내가 얻고싶은 것들이 무엇인지 생각해보았다</p>
<ul>
<li>&lt;타입스크립트로 리액트 프로젝트 완성하기&gt;
이전에 다니던 회사에서는 자바스크립트로 리액트를 사용했었다. 런타임에서 에러가 자꾸 나서 고생했는데 타입스크립트를 쓰면서 어떤 점이 편리한지 느껴보고 싶다.</li>
<li>&lt;좀더 체계적으로 리액트 해보기&gt;
부트캠프 다니면서 배운 것들과 회사에서 필요할때 일주일정도 공부하고 바로 프로젝트 했었는데, 코드를 점점 작성하면서 내가 쓴 코드에 발목이 잡히는 경험을 했었다. portals, redux toolkit, 커스텀 훅을 사용해서 유효성검사하는 법, 특히 리액트 문서의 Thinking in React(<a href="https://beta.reactjs.org/learn/thinking-in-react">링크</a>)를 적용해서 컴포넌트 설계를 체계적으로 해보고 싶다.</li>
<li>&lt;next.js&gt;
내가 들은 강의에서 next.js의 요약강의를 제공해줬었는데, getServerSideProps, getStaticPath 등에 대한 내용을 활용할 수 있다면 좋겠다.</li>
<li>&lt;테스트코드&gt;
TDD의 원칙들을 깊게 체득하는 것은 무리겠지만 jest나 React Testing Library을 사용하는 데 익숙해져서 테스트코드를 작성하는 습관을 들일 수 있는 기초를 마련하고 싶다.</li>
<li>&lt;만든 앱을 사용해서 집청소하기&gt;
내가 코딩해서 만든 결과물이 유용하다는 느낌을 경험하고 싶다.</li>
<li>(당연하지만)&lt;청소에 도움이 되는 투두리스트 어플리케이션&gt;</li>
</ul>
<p>구현하다보면 이 중에 지키지 못하는 것들도 있을 수도 있겠지만 최대한 지키고 싶다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[flowchart]]></title>
            <link>https://velog.io/@ys_sung/flowchart</link>
            <guid>https://velog.io/@ys_sung/flowchart</guid>
            <pubDate>Tue, 07 Mar 2023 06:19:35 GMT</pubDate>
            <description><![CDATA[<ul>
<li>청소 절차 큐레이션 투두리스트.</li>
<li>기획문서(<a href="https://velog.io/@ys_sung/%EA%B8%B0%ED%9A%8D-%EC%B4%88%EC%95%88">link</a>)를 기반으로 플로우차트를 그려보았다.</li>
<li>mermaid(<a href="https://mermaid.js.org/">link</a>)를 사용하였다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ys_sung/post/7cb0e9a4-ceb8-4c9f-800d-aebf432102e6/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[기획 초안]]></title>
            <link>https://velog.io/@ys_sung/%EA%B8%B0%ED%9A%8D-%EC%B4%88%EC%95%88</link>
            <guid>https://velog.io/@ys_sung/%EA%B8%B0%ED%9A%8D-%EC%B4%88%EC%95%88</guid>
            <pubDate>Tue, 07 Mar 2023 02:28:18 GMT</pubDate>
            <description><![CDATA[<h3 id="개요">개요</h3>
<ul>
<li>todoList를 쓰는 이유: 해야할 일을 할 때 &quot;해야될 일들을 떠올리는 과정&quot;과 그 일을 실제로 하면서 &quot;할일을 체크하는 과정&quot;을 분리하기 위해서</li>
<li>ex: 청소를 할 때 (바닥쓸기) - (다음 업무 떠올리기) - (이불털기) - (다음 업무 떠올리기)의 과정이 번거로움</li>
<li>어플의 사용목적: 어플리케이션을 통해 투두리스트를 생성하면 이후에는 그 투두리스트를 해치우는데만 신경쓰면 되도록 투두리스트 큐레이션</li>
<li>과업내용을 청소로 한정한다면? -&gt; 청소가 귀찮은 사람들도 청소를 잘 할 수 있는 투두리스트 생성기! 😎</li>
<li>핵심기능: 청소와 관련된 &quot;질문&quot;을 받아서 잘 짜여진 투두리스트를 만드는 것</li>
<li>-&gt; <strong><em>사용자는 새로운 청소를 시작할 때마다 &quot;질문&quot;에 대답하는 과정을 거쳐야 한다(대신 저장한 청소루틴이 있다면 불러올 것이냐는 질문 통해서 불러오기)</em></strong></li>
</ul>
<h3 id="어플리케이션의-구성요소">어플리케이션의 구성요소</h3>
<ul>
<li><p>&quot;도면&quot; - 전체 집의 조감도, &quot;구역&quot;의 조합으로 이루어져 있다. 시각적 피드백을 확인하는 화면</p>
</li>
<li><p>&quot;구역&quot; - 각 청소해야 하는 구역(거실 | 욕실 | 침실 | 베란다), 자주 사용하는 &quot;구역&quot;을 저장할 수 있다.</p>
<ul>
<li>&quot;남은기간&quot; - &quot;청소리스트&quot;의 &quot;시작, 종료기한&quot;에서 계산된 &quot;남은기간&quot;에 따라서 시각적 피드백이 &quot;도면&quot; 화면에 반영된다.</li>
<li>&quot;팁&quot;</li>
</ul>
</li>
<li><p>&quot;청소리스트&quot; - &quot;구역&quot;에 설정된 청소들의 투두리스트. &quot;청소&quot;들의 순서이면서 &quot;구역&quot;을 구성하는 요소들이다. <del>&quot;구역&quot; 내의 &quot;청소리스트&quot;는 1개이상일 수 있다.</del></p>
<ul>
<li>&quot;시작기간&quot;</li>
<li>&quot;종료기간&quot;</li>
<li>&quot;남은기간&quot;</li>
</ul>
</li>
<li><p>&quot;청소&quot;&lt;카드&gt; - &quot;청소 리스트&quot;를 구성하는 각 태스크(ex: 먼지털기)</p>
<ul>
<li>&quot;체크여부&quot; - 해당 태스크를 수행하였는지 여부. &quot;청소리스트&quot;에 있는 모든 &quot;청소&quot;를 완료하면 초기화된다.</li>
<li>&quot;난이도&quot; - (&quot;매우 귀찮음&quot; | &quot;귀찮음&quot; | &quot;간단함&quot;)</li>
<li>&quot;우선순위&quot; - 우선순위를 기준으로 &quot;청소리스트&quot;에서 순서 결정</li>
<li>&quot;디폴트?&quot; - 해당 구역에서 제외하지 않으면 기본적으로 포함되는지 여부</li>
<li>&quot;청소도구&quot; <ul>
<li>&quot;필수적?&quot;: (&quot;required&quot; | &quot;optional&quot;)</li>
<li>설명: description</li>
</ul>
</li>
<li>&quot;내용&quot; - description</li>
<li>&quot;격려&quot;: 격려메세지 + 구역별 &quot;팁&quot;메시지 </li>
</ul>
</li>
<li><p>flow</p>
<ul>
<li>(도면 생성 화면에서) &quot;구역&quot; 생성 : 구역의 종류(거실 | 욕실 | 침실 | 베란다)를 결정한다</li>
<li>(생성한 구역의 종류에 따른) 질문에 답하면서 여러가지 &quot;청소&quot; 생성 =&gt; &lt;47번째 줄 참고&gt;<ul>
<li>&quot;청소도구&quot;, &quot;팁&quot;은 &quot;청소&quot;에 포함되어 있는 정보</li>
<li>&quot;청소리스트&quot;(=&quot;청소&quot;의 순서가 있는 리스트)는 &quot;청소&quot;들을 생성하는 과정에서 자동으로 결정(&quot;우선순위&quot; 참고)</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="질문의-내용을-어떻게-구성할-것인가가장-중요">질문의 내용을 어떻게 구성할 것인가(가장 중요)</h3>
<ul>
<li>각 &quot;청소&quot;는 고유의 &quot;우선순위&quot;와 &quot;디폴트여부&quot; 값을 가지고 있다</li>
<li>사용자가 특정 &quot;구역&quot;을 생성하면 해당 구역에 맞는 &quot;디폴트&quot; 청소들을 &quot;우선순위&quot;에 맞게 배치한다</li>
<li>질문을 받아서 &quot;청소리스트&quot;를 불러오거나, 청소&quot;를 추가/제거/순서변경 등의 처리를 해서 최종적 &quot;청소리스트&quot;를 생성한다!</li>
</ul>
<h4 id="각-질문이-ui에-어떻게-반영되는지-고려비즈니스-로직">각 질문이 ui에 어떻게 반영되는지 고려(비즈니스 로직)</h4>
<ul>
<li>&quot;청소리스트&quot;에서 &quot;청소&quot;의 순서를 결정하는 데 도움이 되는 질문<ul>
<li>일반적인 청소의 순서를 기반으로 몇개의 질문에 따라 조금씩 커스텀되는 식으로 구현<ul>
<li>디폴트: 기본적으로 삽입되어있는 &quot;청소&quot;들</li>
<li>질문을 받아서 질문리스트를 수정한다</li>
<li>질문의 유형<ul>
<li>분기점을 가르는 질문</li>
<li>특정 &quot;청소&quot;를 리스트에 삽입하는 질문</li>
<li>특정 디폴트 &quot;청소&quot;를 리스트에서 제외하는 질문</li>
<li>&quot;우선순위&quot;가 동일한 청소들의 순서를 결정하는 질문(3개 이상의 경우는 고려 x)</li>
</ul>
</li>
<li>질문의 순서: 큰질문 -&gt; 작은질문</li>
</ul>
</li>
</ul>
</li>
</ul>
<h3 id="주별월별-루틴">주별/월별 루틴</h3>
<ul>
<li>backend 필요한 부분</li>
<li>각 구역별 언제 마지막으로 청소했는지 기록</li>
<li>집 전체의 간략한 &quot;도면&quot;을 그릴 수 있는 단계 추가 <ul>
<li>이후 각 구역을 선택해서 청소를 실시할 수 있다</li>
<li>각 투두리스트의 항목은 (&quot;시작기한&quot;, 주별/월별에 따라 계산된 &quot;만료기간&quot;, 시작기한, 만료기간에서 계산된 &quot;남은기간&quot;) 정보를 가지고 있다</li>
<li>각 구역의 &quot;남은기간&quot;들에서 공간 전체의 &quot;청소 진척도&quot;를 계산해서 &quot;도면&quot;을 보여주는 화면에서 시각적인 피드백(ex: 진척도에 따라 빨-&gt;초 배경색) 표출</li>
</ul>
</li>
</ul>
<h3 id="팁취소">팁(취소)</h3>
<ul>
<li><p><del>팁을 줌으로써 청소의 방향을 유도할수도(거실의 먼지털기, 침실의 먼지털기... -&gt; 거실의 바닥닦기, 침실의 바닥닦기)</del></p>
</li>
<li><p><del>그러려면 팁은 그 팁의 내용에 따라 적절한 곳에서 표출되어야 한다</del></p>
</li>
<li><p><del>일반적인 내용보다는 지금 수행하고 있는 청소에 도움이 되는 팁이었으면 좋겠다</del></p>
</li>
<li><p><del>팁의 종류들(카테고리: [마음가짐], [공통], [침실/주방/욕실/베란다])</del></p>
</li>
<li><p><del>언제 표출할 것인지?</del>
<del>1. 각 투두리스트를 완료했을 때 피드백으로 활용? -&gt; 쓰기 번거롭지 않을까?</del>
<del>2. 하나의 구역은 완료했을 때 -&gt; &quot;다음 구역으로 넘어가시겠습니까&quot; 팝업창 + 팁메시지</del>
<del>- 다른 곳은 없을까? -&gt; 일단 플로우차트를 그린 후에 다시 생각해보자</del></p>
</li>
</ul>
<h3 id="대기질-open-api취소">대기질 open api(취소)</h3>
<ul>
<li><del>청소를 실시하기 직전에 체크</del></li>
<li><del>미세먼지 체크 -&gt; 미세먼지가 일정 수치 이상이라면.. -&gt; (필요한 작업들 소개)</del></li>
<li><del>필요한 작업들: 창문틀 청소하기, 청소기보다 물청소</del></li>
</ul>
<h3 id="커뮤니티-기능취소">커뮤니티 기능(취소)</h3>
<ul>
<li><del>유저들이 의견 나누는 커뮤공간</del></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[청소 작업 목록]]></title>
            <link>https://velog.io/@ys_sung/%EC%B2%AD%EC%86%8C-%EC%9E%91%EC%97%85-%EB%AA%A9%EB%A1%9D</link>
            <guid>https://velog.io/@ys_sung/%EC%B2%AD%EC%86%8C-%EC%9E%91%EC%97%85-%EB%AA%A9%EB%A1%9D</guid>
            <pubDate>Tue, 07 Mar 2023 02:22:10 GMT</pubDate>
            <description><![CDATA[<h3 id="청소">청소</h3>
<ul>
<li><p>&quot;청소&quot;&lt;카드&gt; - &quot;청소 리스트&quot;를 구성하는 각 태스크(ex: 먼지털기)</p>
<ul>
<li>&quot;체크여부&quot; - 해당 태스크를 수행하였는지 여부. &quot;청소리스트&quot;에 있는 모든 &quot;청소&quot;를 완료하면 초기화된다.(*투두리스트가 결정된 이후에 생성된다)</li>
<li>&quot;난이도&quot; - (&quot;너무귀찮음&quot; | &quot;귀찮음&quot; | &quot;간단함&quot;)</li>
<li>&quot;우선순위&quot; - 우선순위를 기준으로 &quot;청소리스트&quot;에서 순서 결정</li>
<li>&quot;디폴트?&quot; - 해당 구역에서 제외하지 않으면 기본적으로 포함되는지 여부</li>
<li>&quot;청소도구&quot; <ul>
<li><del>&quot;필수적?&quot;: (&quot;required&quot; | &quot;optional&quot;)</del></li>
<li><del>설명: description</del></li>
</ul>
</li>
<li>&quot;내용&quot; - description</li>
<li>&quot;격려&quot;: 격려메세지 + 구역별 &quot;팁&quot;메시지 </li>
</ul>
</li>
<li><p>&quot;쉬움&quot;, &quot;귀찮음&quot;은 제외하는 질문, &quot;너무 귀찮음&quot;은 추가하는 질문</p>
</li>
<li><p>&lt;공통&gt; (1<del>19) / (81</del>100)</p>
<table>
<thead>
<tr>
<th>이름</th>
<th>난이도</th>
<th>우선순위</th>
<th>디폴트여부</th>
<th>청소도구</th>
<th>격려메시지</th>
<th>비고</th>
</tr>
</thead>
<tbody><tr>
<td>환기</td>
<td>간단함</td>
<td>1</td>
<td>y</td>
<td>없음</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>세탁하기</td>
<td>귀찮음</td>
<td>10</td>
<td>n</td>
<td>없음</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>빨래개기</td>
<td>귀찮음</td>
<td>100</td>
<td>n</td>
<td>없음</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>빨래널기</td>
<td>귀찮음</td>
<td>100</td>
<td>n</td>
<td>없음</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>빨래수납</td>
<td>귀찮음</td>
<td>100</td>
<td>n</td>
<td>없음</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>현관바닥청소</td>
<td>귀찮음</td>
<td>90</td>
<td>n</td>
<td>빗자루</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>쓰레기버리기</td>
<td>귀찮음</td>
<td>90</td>
<td>n</td>
<td>없음</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>쓰레기통비우기</td>
<td>귀찮음</td>
<td>90</td>
<td>n</td>
<td>쓰레기봉투</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>창문청소</td>
<td>너무귀찮음</td>
<td>50</td>
<td>n</td>
<td>걸레</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>분리수거</td>
<td>너무귀찮음</td>
<td>90</td>
<td>n</td>
<td>없음</td>
<td>-</td>
<td></td>
</tr>
</tbody></table>
</li>
</ul>
<ul>
<li><p>&lt;침실&gt; (20~80)</p>
<table>
<thead>
<tr>
<th>이름</th>
<th>난이도</th>
<th>우선순위</th>
<th>디폴트여부</th>
<th>청소도구</th>
<th>격려메시지</th>
<th>비고</th>
</tr>
</thead>
<tbody><tr>
<td>이불개기</td>
<td>간단함</td>
<td>20</td>
<td>y</td>
<td>없음</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>먼지털기</td>
<td>간단함</td>
<td>30</td>
<td>y</td>
<td>없음</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>옷정리</td>
<td>간단함</td>
<td>70</td>
<td>n</td>
<td>없음</td>
<td></td>
<td></td>
</tr>
<tr>
<td>물건정리</td>
<td>귀찮음</td>
<td>20</td>
<td>y</td>
<td>없음</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>이불털기</td>
<td>귀찮음</td>
<td>20</td>
<td>n</td>
<td>없음</td>
<td>-</td>
<td></td>
</tr>
<tr>
<td>청소기돌리기(침실)</td>
<td>귀찮음</td>
<td>50</td>
<td>n</td>
<td>청소기</td>
<td></td>
<td></td>
</tr>
<tr>
<td>바닥쓸기(침실)</td>
<td>귀찮음</td>
<td>50</td>
<td>n</td>
<td>빗자루</td>
<td></td>
<td></td>
</tr>
<tr>
<td>바닥닦기(침실)</td>
<td>귀찮음</td>
<td>60</td>
<td>n</td>
<td>물걸레/청소포</td>
<td></td>
<td></td>
</tr>
<tr>
<td>높은곳먼지털기</td>
<td>너무귀찮음</td>
<td>30</td>
<td>n</td>
<td>없음</td>
<td></td>
<td></td>
</tr>
<tr>
<td>침대,이불커버세탁</td>
<td>너무귀찮음</td>
<td>40</td>
<td>n</td>
<td>없음</td>
<td></td>
<td></td>
</tr>
<tr>
<td>침대밑청소</td>
<td>너무귀찮음</td>
<td>40</td>
<td>n</td>
<td>빗자루, 청소기, 물걸레/청소포</td>
<td></td>
<td></td>
</tr>
<tr>
<td>쿠션빨래</td>
<td>너무귀찮음</td>
<td>40</td>
<td>n</td>
<td>없음</td>
<td></td>
<td></td>
</tr>
</tbody></table>
</li>
</ul>
<ul>
<li><p>&lt;주방&gt; (20~80)</p>
<table>
<thead>
<tr>
<th>이름</th>
<th>난이도</th>
<th>우선순위</th>
<th>디폴트여부</th>
<th>청소도구</th>
<th>격려메시지</th>
<th>비고</th>
<th></th>
<th>내용</th>
</tr>
</thead>
<tbody><tr>
<td>설거지</td>
<td>간단함</td>
<td>20</td>
<td>n</td>
<td>주방세제</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>수세미열탕소독</td>
<td>간단함</td>
<td>21</td>
<td>n</td>
<td>없음</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>싱크대청소</td>
<td>간단함</td>
<td>30</td>
<td>n</td>
<td>베이킹소다</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>바닥쓸기(주방)</td>
<td>귀찮음</td>
<td>20</td>
<td>y</td>
<td>빗자루</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>청소기돌리기(주방)</td>
<td>귀찮음</td>
<td>50</td>
<td>n</td>
<td>청소기</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>바닥닦기(침실)</td>
<td>귀찮음</td>
<td>60</td>
<td>n</td>
<td>물걸레/청소포</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>전자레인지청소</td>
<td>귀찮음</td>
<td>70</td>
<td>n</td>
<td>물걸레/청소포</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>음식물쓰레기버리기</td>
<td>귀찮음</td>
<td>80</td>
<td>n</td>
<td>없음</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>오븐청소</td>
<td>너무귀찮음</td>
<td>70</td>
<td>n</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>가스레인지청소</td>
<td>너무귀찮음</td>
<td>70</td>
<td>n</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>식기세척기청소</td>
<td>너무귀찮음</td>
<td>70</td>
<td>n</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>배수구청소</td>
<td>너무귀찮음</td>
<td>70</td>
<td>n</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>냉장고청소</td>
<td>너무귀찮음</td>
<td>70</td>
<td>n</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
</li>
</ul>
<ul>
<li><p>&lt;욕실&gt; (20~80)</p>
<table>
<thead>
<tr>
<th>이름</th>
<th>난이도</th>
<th>우선순위</th>
<th>디폴트여부</th>
<th>청소도구</th>
<th>격려메시지</th>
<th>비고</th>
<th></th>
<th>내용</th>
</tr>
</thead>
<tbody><tr>
<td>물뿌리기</td>
<td>간단함</td>
<td>20</td>
<td>y</td>
<td>없음</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>배수구 뜨거운물 붓기</td>
<td>간단함</td>
<td>20</td>
<td>n</td>
<td>끓인물</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>세정제칠하기</td>
<td>귀찮음</td>
<td>40</td>
<td>n</td>
<td>세정제</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>바닥솔질</td>
<td>귀찮음</td>
<td>60</td>
<td>n</td>
<td>청소용솔</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>벽면솔질</td>
<td>귀찮음</td>
<td>60</td>
<td>n</td>
<td>청소용솔</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>천장청소</td>
<td>너무귀찮음</td>
<td>60</td>
<td>n</td>
<td>청소용솔</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>변기청소</td>
<td>귀찮음</td>
<td>60</td>
<td>n</td>
<td>청소용솔</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>세면대청소</td>
<td>귀찮음</td>
<td>60</td>
<td>n</td>
<td>안쓰는 칫솔 등</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>배수구청소(욕실)</td>
<td>너무귀찮음</td>
<td>80</td>
<td>n</td>
<td>끓인물, 베이킹소다 등</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>곰팡이청소</td>
<td>너무귀찮음</td>
<td>80</td>
<td>n</td>
<td>곰팡이 제거제, 청소용솔</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
</li>
</ul>
<ul>
<li><p>&lt;베란다&gt; (20~80)</p>
<table>
<thead>
<tr>
<th>이름</th>
<th>난이도</th>
<th>우선순위</th>
<th>디폴트여부</th>
<th>청소도구</th>
<th>격려메시지</th>
<th>비고</th>
<th></th>
<th>내용</th>
</tr>
</thead>
<tbody><tr>
<td>물건정리</td>
<td>귀찮음</td>
<td>20</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>바닥닦기(베란다)</td>
<td>귀찮음</td>
<td>30</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>바닥쓸기(베란다)</td>
<td>귀찮음</td>
<td>40</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
</li>
</ul>
<ul>
<li><p>&lt;계절청소&gt; (20~80) (난이도 구분x/순서구분x)</p>
<table>
<thead>
<tr>
<th>이름</th>
<th>난이도</th>
<th>디폴트여부</th>
<th>청소도구</th>
<th>격려메시지</th>
<th>비고</th>
<th></th>
</tr>
</thead>
<tbody><tr>
<td>커튼청소</td>
<td>계절청소</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>옷장체크</td>
<td>계절청소</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>침구교체</td>
<td>계절청소</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>에어컨필터청소</td>
<td>계절청소</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>선풍기청소</td>
<td>계절청소</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>냉장고청소</td>
<td>계절청소</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>환기팬 청소</td>
<td>계절청소</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>세탁기필터교체</td>
<td>계절청소</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td>신발장청소</td>
<td>계절청소</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
</li>
</ul>
<h3 id="청소도구">청소도구</h3>
<ul>
<li>물걸레 청소포</li>
<li>주방세제(중성세지인지 확인)<ul>
<li>욕실에서는 원액 그대로 거품내서 사용</li>
<li>거실이나 변기는 희석해서 스프레이 용기에 담는다</li>
</ul>
</li>
<li>스프레이 용기</li>
<li>세제</li>
<li>청소솔</li>
<li>막대걸레</li>
<li>테이프클리너</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[청소 질문리스트]]></title>
            <link>https://velog.io/@ys_sung/%EC%B2%AD%EC%86%8C-%EC%B2%B4%ED%81%AC%EB%A6%AC%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@ys_sung/%EC%B2%AD%EC%86%8C-%EC%B2%B4%ED%81%AC%EB%A6%AC%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Tue, 07 Mar 2023 02:19:35 GMT</pubDate>
            <description><![CDATA[<h3 id="질문">질문</h3>
<ul>
<li><p>질문의 유형</p>
<ul>
<li><p>분기점을 가르는 질문[type: choice]</p>
</li>
<li><p>특정 &quot;청소&quot;를 리스트에 삽입하는 질문[type: add]</p>
</li>
<li><p>특정 디폴트 &quot;청소&quot;를 리스트에서 제외하는 질문[type: remove]</p>
</li>
<li><p>&quot;우선순위&quot;가 동일한 청소들의 순서를 결정하는 질문[type: sort]</p>
</li>
<li><p>[choice]</p>
<ul>
<li><p>공통</p>
<ul>
<li>청소할 구역이 어디인가요? (&quot;침실&quot; | &quot;주방&quot; | &quot;욕실&quot; | &quot;베란다&quot;) -&gt; 구역에 맞는 디폴트 &quot;청소&quot; 생성</li>
<li>선택하신 ${구역}에 미완료된 청소가 있습니다. 이어서 청소할까요 -&gt; 진행중인 청소리스트 불러오고 질문 종료</li>
<li>선택하신 ${구역}에 즐겨찾기한 &quot;청소리스트&quot;(n개)가 있습니다. &quot;청소리스트&quot;를 불러올까요?  -&gt; yes 선택시 해당 &quot;청소리스트&quot; 불러오고 질문 종료</li>
<li>계절맞이 청소를 실시할까요? -&gt; yes 선택시 계절청소로 분류된 청소들 필터링</li>
<li>얼마나 귀찮으세요?? (&quot;엄청 귀찮아..&quot; | &quot;조금 귀찮아..&quot; | &quot;청소좀 해볼까!&quot;) -&gt; 난이도 기준으로 필터링, (*질문들도 필터링)</li>
</ul>
</li>
<li><p>우선순위가 겹치는 질문 있을 때 질문</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<ul>
<li><p>[add/remove]</p>
<ul>
<li><p>공통</p>
<ul>
<li><p>청소하는 데 방해되는 짐들이 많습니까? -&gt; &lt;짐치우기&gt; 추가</p>
</li>
<li><p>청소 후 버려야할 쓰레기가 있습니까? -&gt; &lt;쓰레기버리기&gt; 추가</p>
</li>
<li><p>세탁할 빨래가 있습니까? -&gt; &lt;세탁하기&gt; 추가</p>
<ul>
<li>가장 뒤에 &lt;빨래개기&gt; 추가</li>
<li>가장 뒤에 &lt;빨래널기&gt; 추가</li>
<li>가장 뒤에 &lt;빨래수납&gt; 추가</li>
</ul>
</li>
<li><p>세탁이 끝난 빨래가 있습니까 -&gt; &lt;빨래널기&gt; 추가</p>
</li>
<li><p>다 마른 빨래가 있습니까&gt; -&gt; &lt;빨래수납&gt; 추가</p>
</li>
<li><p>&lt;너무귀찮음 질문&gt;</p>
</li>
<li><p>오늘이 분리수거를 하는 날인가요? -&gt; &lt;분리수거&gt; 추가</p>
</li>
<li><p>창문 닦은지 오래됐나요&gt; -&gt; &lt;창문청소&gt; 추가</p>
</li>
</ul>
</li>
<li><p>침실 </p>
<ul>
<li><p>청소에 방해되는 물건들을 정리해야 하나요 -&gt; &lt;물건정리&gt; 추가</p>
</li>
<li><p>이불 먼지를 털어볼까요? -&gt; &lt;이불털기&gt; 추가</p>
</li>
<li><p>바닥 청소를 하실건가요? -&gt; &lt;청소기돌리기&gt; 제거</p>
<ul>
<li>혹시 진공청소기가 없나요? -&gt; yes면 &lt;청소기돌리기&gt;를 &lt;바닥쓸기&gt;로 대체</li>
</ul>
</li>
<li><p>바닥을 닦으실 건가요? -&gt; &lt;바닥닦기&gt;추가</p>
</li>
<li><p>이불 빨래한지 오래됐나요? -&gt; &lt;침대커버,이불청소&gt; 추가</p>
</li>
<li><p>&lt;너무귀찮음 질문&gt;</p>
</li>
<li><p>높은 곳 먼지를 먼저 청소하는 게 좋아요. 추가할까요? -&gt; &lt;높은곳/구석진곳먼지털기&gt; 추가</p>
</li>
<li><p>오랜만에 이불/침대커버 등을 세탁해볼까요? -&gt; &lt;침대,이불커버세탁&gt; 추가</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<pre><code> - 주방 
   - 설거지거리가 있나요? -&gt; &lt;설거지&gt; 추가, &lt;수세미 열탕소독&gt; 추가
   - 간단히 싱크대를 닦아볼까요? -&gt; &lt;싱크대청소&gt; 추가
   - 바닥 청소를 하실건가요? -&gt; &lt;청소기돌리기&gt; 제거
    - 혹시 진공청소기가 없나요? -&gt; yes면 &lt;청소기돌리기&gt;를 &lt;바닥쓸기&gt;로 대체
   - 바닥을 닦으실 건가요? -&gt; &lt;바닥닦기&gt; 추가

   - &lt;너무귀찮음 질문&gt;
   - 음식물 쓰레기를 버리러 갈래요? -&gt; &lt;음식물쓰레기&gt; 추가
   - 청소할 주방기구들을 선택해주세요 -&gt; (전자레인지 / 오븐 / 가스레인지 / 식기세척기 / 냉장고) 다중선택 후 선택한 청소추가
   - 오랜만에 배수구청소는 어떠신가요 -&gt; &lt;배수구청소&gt; 추가

 - 욕실
   - 세제청소 하실 건가요? -&gt; &lt;세정제칠하기&gt; 추가
     - 청소할 구역을 선택해주세요 -&gt; (바닥 | 벽면 | 천장 | 세면대 | 변기) 다중선택 후 선택한 청소추가
     - &lt;바닥솔질&gt; &lt;벽면솔질&gt; &lt;천장청소&gt; &lt;세면대청소&gt; &lt;변기청소&gt;
   - 배수구청소를 할까요? -&gt; &lt;배수구청소&gt; 추가
   - 곰팡이가 피었나요? -&gt; &lt;곰팡이청소&gt; 추가</code></pre><ul>
<li>[sort]<ul>
<li>공통<ul>
<li>동일한 우선순위 카드 2개이상인 경우 -&gt; 순서 선택할 수 있는 ui 제공</li>
<li>도구에 관한 질문 -&gt; 체크박스로 선택할 수 있는 ui 제공</li>
</ul>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Redux 내용정리]]></title>
            <link>https://velog.io/@ys_sung/Redux-%EB%82%B4%EC%9A%A9%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@ys_sung/Redux-%EB%82%B4%EC%9A%A9%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Mon, 26 Apr 2021 03:08:35 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://www.robinwieruch.de/react-redux-tutorial">https://www.robinwieruch.de/react-redux-tutorial</a> 의 &#39;React Redux Tutorial for Beginners [2019]&#39;를 읽고 개인적으로 학습하고 요약 정리한 내용입니다.</p>
</blockquote>
<h3 id="js-라이브러리의-간단한-역사">JS 라이브러리의 간단한 역사</h3>
<ul>
<li><p>예전에는 자바스크립트 라이브러리로 jQuery가 유일했었다. DOM을 조작할 수 있었고, 위젯을 재사용하고 애니메이션 효과를 줄 수 있는 유용한 라이브러리였다.</p>
</li>
<li><p>하지만 어플리케이션의 사이즈가 커져가면서 JS코드의 사이즈가 커졌었고 이것은 스파게티 코드를 작성하게 되는 요인이 되기도 했다.</p>
</li>
<li><p>이런 jQuery의 한계를 극복하기 위한 프레임워크(또는 라이브러리)가 등장했다. 이것들은 더 나은 아키텍쳐를 제공하고 특히 문제를 해결하기 위해 개발자가 SPA(<em>Single Page Applicateion</em>)로 프론트엔드 어플리케이션을 만들 수 있도록 하였다.</p>
</li>
<li><p>Angular, Ember, Backbone과 같은 프레임워크들이 그렇게 급부상했다. 하지만 어플리케이션의 사이즈가 증가하면서 이러한 것들도 새로운 한계에 부딪혔다. <strong>그것은 바로 상태 관리(State Management)이다.</strong> 이런 프레임워크들은 상태를 양방향으로 관리하기 때문에 규모가 커질 수록 상태 관리에 애를 먹었던 것이다.</p>
</li>
<li><p>그래서 등장한 것이 React이다. React는 이전의 프레임워크와 달리 View Layer만 영향을 미쳤는데, 이런 React가 상태를 관리하는 법은 Local State를 활용하는 방법이었다. React에서 State는 상위에서 하위로 흐르는 단방향이기 때문에 코드의 결과를 더 예측하기가 쉬웠다.</p>
</li>
<li><p>하지만 역시 상태 관리 문제가 여전히 해결된 건 아니었다. 이전의 프레임워크만큼 심각한 문제는 아니지만 여전히 React에서도 문제가 남아있었다.</p>
</li>
<li><p>React를 만든 페이스북에서는 이런 문제를 해결하기 위해 <strong>Flux Architecture</strong>를 소개한다.</p>
</li>
</ul>
<h3 id="flux-architecture">Flux Architecture</h3>
<ul>
<li><p>Flux Architecture는 <strong>Action, Dispatcher, Store, View</strong>라는 네가지 핵심 요소로 이루어진다.</p>
</li>
<li><p>네 가지 요소가 상호작용하는 과정은 다음과 같다.</p>
<blockquote>
<ol>
<li>사용자는 브라우저에서 View에 상호작용(ex. 클릭)을 함으로써 Action을 트리거한다.</li>
<li>Action은 State를 업데이트하는 데 필요한 정보를 갖고 있다.</li>
<li>Dispatcher는 Action을 스토어에 전달한다.</li>
<li>새로운 State가 Store에 전달된다</li>
<li>View 업데이트!</li>
</ol>
</blockquote>
</li>
<li><p>이렇게 보듯이 데이터는 단방향으로 흐른다. <em>View에서 Action을 트리거해서 Dispatcher와 Store에 전달되고, 최종적으로 View는 새로운 상태를 반영한다.</em></p>
</li>
</ul>
<h3 id="reduxreducer--flux">Redux(Reducer + Flux)</h3>
<ul>
<li><p>리덕스는 Flux Architecture의 많은 부분을 차용했지만 모든 것은 아니다. </p>
</li>
<li><p>예를 들어 리덕스의 Store는 singletone이다. 한 프로젝트에 Store는 하나만 존재한다. 반면에 Dispatcher는 하나가 아니었다. 리덕스에서는 대신 여러개의 Reducer를 사용했다. 이 Reducer가 Action을 전달받아서 State를 변화시킨다.</p>
</li>
</ul>
<h4 id="redux의-요소들">Redux의 요소들</h4>
<p><img src="https://images.velog.io/images/ys_sung/post/06c3d1c5-a19b-4421-915c-a6815613c82d/reduxFlow.png" alt=""></p>
<h5 id="action">Action</h5>
<ul>
<li>type과 payload로 이루어져 있다.(payload는 optional)</li>
<li>type는 Reducer가 액션을 구분하기 위해 사용하며 문자열이다.</li>
<li>payload는 어떤 타입이든 상관없다. 변화시킬 state의 본문(내용)이다.</li>
<li>Action은 Reducer 함수에 전달된다.</li>
</ul>
<h5 id="reducer">Reducer</h5>
<ul>
<li>리듀서는 오직 action type만 해석할 수 있다.</li>
<li>Switch/Case 문을 이용해서 type을 분기한다.</li>
<li>default 문을 이용해서 state가 변화하지 않는 조건문 작성한다.</li>
<li>각 조건문 안에서 state에 변화를 주는 로직 작성한다.</li>
</ul>
<blockquote>
<ol>
<li>to-do-list 추가의 경우: concat으로 불변성 유지하면서 배열에 요소 추가</li>
<li>toggle-switch의 경우: 액션의 payload로 전달받은 id와 map메소드(immutable)를 이용해서  사용해서 배열에서 해당 id를 갖는 요소를 찾아서 해당 요소를 변경시켜준다(여전히 immutable하게! Object.assign 사용)</li>
</ol>
</blockquote>
<ul>
<li>Reducer 함수를 간략하게 만드려면 Case문 내부의 로직을 바깥의 함수로 추출해내면 된다.</li>
</ul>
<h5 id="store">Store</h5>
<ul>
<li>앞서 본 Action(state를 트리거)과 Reducer(이전 state와 action에 새로운 state를 첨가)하는 로직들을 아우르는 역할을 한다.</li>
<li>질문들<blockquote>
<ol>
<li>어디서 action을 trigger하는가</li>
<li>누가 reducer에 action을 전달하는가</li>
<li>뷰에 업데이트된 state를 반영하기 위해서 state를 어디서 가져와야 하는가</li>
</ol>
</blockquote>
</li>
<li>답은 모두 <strong>Redux Store</strong>다!</li>
<li>Store는 flux와 다르게 프로젝트에서 하나만 존재하는 Global Object다.<pre><code class="language-javascript">//스토어는 리덕스에서 import해서 가져온다.
//createStore함수는 reducer를 인자로 받는다. 두번째 인자는 state의 초기값
//리액트와 리덕스를 같이 사용할 때는 아래와 다른 방식으로 초기값을 설정한다: 스토어가 아니라 리듀서 함수에서 초기값 설정
import { createStore } from &#39;redux&#39;;
const store = createStore(reducer, []);
</code></pre>
</li>
</ul>
<pre><code>- Store로 할 수 있는 것들
```javascript
store.dispatch(action)
//액션을 dispatch할 수 있다.(state update)
store.getState()
//현재 state를 읽어올 수 있다.
const unsubscribe = store.subscribe() unsubscribe() 
//state의 변화를 view에 반영하거나 반영하지 않게 할 수 있다
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Final Project 회고록:  프로젝트 <puzzle>]]></title>
            <link>https://velog.io/@ys_sung/Final-Project-%ED%9A%8C%EA%B3%A0%EB%A1%9D-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-puzzle</link>
            <guid>https://velog.io/@ys_sung/Final-Project-%ED%9A%8C%EA%B3%A0%EB%A1%9D-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-puzzle</guid>
            <pubDate>Mon, 05 Apr 2021 11:24:31 GMT</pubDate>
            <description><![CDATA[<p> Final Project를 마무리하였다.
 코드스테이츠의 수강생들 4명이 팀으로 모여 한달간 진행했던 프로젝트였다. 나는 백엔드로서 팀에 참여하였는데, First Project에서는 프론트였기 때문에 다양한 경험을 해보고 싶은 생각에 선택했다.
 <strong><em>이 글은 프로젝트가 마무리되고 리팩토링을 거친 후에 작성하는 회고록이다.</em></strong>
<a href="https://www.teampuzzle.ga">프로젝트 &#39;퍼즐&#39; 바로가기</a>
 <img src="https://images.velog.io/images/ys_sung/post/df2f452a-f3e5-4684-a691-dd33465bbc03/puzzleDemo.gif" alt=""></p>
<h3 id="발상과-기획">&lt;발상과 기획&gt;</h3>
<p>∘ 처음에 팀에서 나온 아이디어는 &#39;<em>희귀템 알리미</em>&#39;였다. 현상수배를 컨셉으로 찾기 어려운 물건들(ex- 예전의 허니버터칩)을 등록하면 다른 유저들이 그 물건 위치를 공유할 수 있게 하자는 아이디어였다. <strong>하지만 커뮤니티 기반의 서비스는 실제 유저들이 있어야 제대로 돌아가는지 알 수 있다는 의견</strong>에 따라서 그동안 짰던 와이어프레임을 뒤엎고 다시 발상단계로 돌아갔다.</p>
<p>∘ 그래서 다음에 나온 아이디어가 바로 <strong>유저가 업로드한 이미지로 만들어진 퍼즐로 진척도를 알 수 있게 하는 협업툴</strong>이었다. Forest라는 시간관리 어플이 있다. 타이머를 켜면 다른 어플들이 잠겨서 할일에 집중하게 만들고 정한 시간동안 집중을 했다면 유저의 개인 정원에 나무를 심을 수 있는 보상을 주는 어플이다. 우리 팀은 Forest 어플의 아이디어 중에서 &#39;업무를 진행시키면 시각적인 보상을 주자&#39;는 부분을 협업툴에 접목하는 것이 괜찮은 아이디어라고 생각했다. 그리고 그 &#39;시각적인 보상&#39; 으로서 같이 완성한다는 느낌을 주는 데에는 퍼즐이 협업툴과 어울렸기 때문에 해당 아이디어가 채택되었다.</p>
<p><em>그렇게 기획단계를 마무리하고 실제 구현에 들어가게 되는데...</em></p>
<p><img src="https://images.velog.io/images/ys_sung/post/9a7d8129-4cc8-4a58-a690-f1c00b23e420/%EC%99%80%EC%9D%B4%EC%96%B4%ED%94%84%EB%A0%88%EC%9E%84before.png" alt=""><img src="https://images.velog.io/images/ys_sung/post/a3b9af18-54b5-4223-a003-66b15bd177bb/%EA%B8%B0%EB%8A%A5%ED%94%8C%EB%A1%9C%EC%9A%B0before.png" alt=""><em>(기획단계의 기능 플로우, 와이어프레임)</em></p>
<h3 id="이미지를-도대체-어떻게-쪼갤-것인가">&lt;이미지를 도대체 어떻게 쪼갤 것인가?!&gt;</h3>
<p>∘ 나는 프로젝트 기간동안 백엔드로서 주로 <strong>이미지 처리와 관련된 api 엔드포인트 기능</strong> (이미지 업로드, 프로젝트 진행도와 조각난 이미지 동기화 등)을 만드는 데 주력했다. 이 프로젝트의 중요한 부분은 이미지 처리라고 생각해서 꼭 해보고 싶었기 때문이었다. </p>
<p>∘ 유저가 프로젝트 이미지를 업로드하면 그 이미지를 쪼개어서 프로젝트가 진행될 수록 더 많은 조각을 볼 수 있게 처리해야 했다. 처음에는 프로젝트 내의 업무(=태스크 카드) 하나당 이미지 한 조각을 연동 시키려고 했었다. 즉 프로젝트가 전체 퍼즐이라면 하나의 업무는 퍼즐 한조각인 셈이었다. 프로젝트 내의 모든 업무를 완료하면 이미지는 완성된 퍼즐이 되는 것이다. 이미지를 나누는 것자체가 큰일이었지만 그보다 더 큰 문제는 프로젝트 진행 중에 새로운 업무를 추가시켰을 때, 퍼즐 한 조각의 크기가 달라지는 것이다. 새 업무를 추가시키는 건 협업을 하다보면 반드시 필요한 기능이었기 때문에 프로젝트 생성할 때 전체 퍼즐의 갯수를 정하는 것은 의미가 없었다.</p>
<p><img src="https://images.velog.io/images/ys_sung/post/e8bcebbd-8bf2-4e0a-871f-846da2c7a24e/%ED%8D%BC%EC%A6%90_%EC%A1%B0%EA%B0%81_%ED%81%AC%EA%B8%B0.png" alt=""><em>(업무 개수가 늘어나면 하나의 퍼즐 크기가 달라진다. 더불어 퍼즐조각 개수가 NxN개가 아닐 때 어떻게 처리해야할지에 대한 문제도 있었다)</em></p>
<h4 id="challenge1-백엔드에서-어떻게든-해결하자">&lt;Challenge1: 백엔드에서 어떻게든 해결하자!&gt;</h4>
<p>∘ <strong>STEP1</strong> : 유저가 전체 프로젝트 이미지 한장을 업로드하면, 서버에서 (업무 하나) / (전체 업무 개수)의 크기만큼 이미지를 잘라서 다시 응답해보자!</p>
<p>∘ <strong>STEP2</strong> : 업무 개수가 늘어날 때마다 새로운 비율로 이미지를 잘라서 S3에 저장하면 업로드 횟수가 너무 많아진다. 10조각인 프로젝트에 업무를 추가하면 이미지를 다시 11조각으로 자르는데 10조각일 때와 조각 크기가 다르기 때문에 새로 자른 11조각 모두를 업로드해야되기 때문이다. </p>
<p>∘ <em><strong>STEP3</strong></em> : 그럼 서버에서 이미지를 자르는 작업을 수행하고 DB에 좌표값만 업로드하면 되지 않을까? 가능하기만 하다면 가장 이상적인 방법이겠지만 문제는 그렇게 이미지를 세밀하게 자르는 복잡한 연산을 설계할 능력이 나에게 없었다.</p>
<p>∘ 이쯤 되어서 프로젝트 마감기간이 다가왔고, 프론트엔드를 맡으신 팀원분이 이미지 자르는 것은 프론트엔드에서 어떻게든 할 것이니 전체 이미지 업로드 기능만 구현해달라고 하셨다. 그래서  multer와 multerS3로 이미지를 S3에 업로드하고 이미지 경로를 클라이언트에 응답하는 식으로 처리를 했고, 이미지 슬라이스는 팀원끼리 머리를 싸매었지만 끝내 뾰족한 수가 없이 프로젝트 기간이 마무리되고 말았다. 프로젝트 이름이 Puzzle인데 퍼즐기능이 완벽하지 않다니! 너무 분했다.</p>
<p><img src="https://images.velog.io/images/ys_sung/post/d554dd67-abac-4677-bb2e-685f24649b56/flow_problem.png" alt=""><em>(고민의 흔적)</em></p>
<h4 id="challenge2-프론트엔드에서-못다한-일들을-마무리짓자">&lt;Challenge2: 프론트엔드에서 못다한 일들을 마무리짓자! &gt;</h4>
<p>∘ <strong>리팩토링 기간동안 나는 프론트엔드를 맡았다.</strong> 내가 백엔드에서 마무리 짓지 못한 이미지 자르기 기능을 프론트사이드에서 꼭 설욕하고 싶었다. 일단 먼저 나는 지금 나의 능력의 한계를 인정하는 데서부터 시작하기로 했다. 업무가 추가될 때마다 적절한 크기로 이미지를 자르는 것은 포기하였다. 퍼즐 한 조각의 크기는 고정되어야 한다.</p>
<p>∘ 그런데 생각해보면 우리 프로젝트는 실제 퍼즐게임을 하는 것이 아니라, 프로젝트가 진행되면서 이미지의 일부가 퍼즐이 맞춰지는 것처럼 보여지기만 하면 된다. 직소퍼즐처럼 조각들이 뒤섞여있는 것이 아니기 때문에 실제 이미지를 자를 필요가 없다! </p>
<p>∘ 그래서 떠올린 것이 <strong>css grid로 10x10 그리드를 만들고, 서버에서 넘겨준 프로젝트 진행 %에 대응하여 grid를 이미지 뒤로 숨긴다는 아이디어</strong>였다. 즉, 퍼즐 조각 하나가 1%인 셈이다. 퍼즐 전체 개수에 따라서 퍼즐 하나의 크기 비율을 계산하는 것은 어렵지만 퍼센트는 계산하기 간단하기 때문에 문제가 더 쉬워졌다. 그렇다고 하더라도 마냥 간단한 것은 아니었다. 이미지를 자를 필요는 없었지만 업무 하나를 추가하거나 삭제할 때 전체 업무 개수가 달라지고, 그에 따라 새로 %를 계산해야했기 때문이다. </p>
<p><img src="https://images.velog.io/images/ys_sung/post/3a0af134-0097-430d-a8d4-7397dbb77405/%ED%8D%BC%EC%A6%9020.png" alt="진행도20%"><em>(진행도 20%)</em>
<img src="https://images.velog.io/images/ys_sung/post/54373382-3958-416b-9651-8f11c8bedc7c/%ED%8D%BC%EC%A6%9080.png" alt="진행도80%"><em>(진행도 80%)</em></p>
<p>∘ <em><strong>이번에는 아이디어대로 기능을 구현할 수 있었다.</strong></em>  프로젝트 동안 내가 작성한 백엔드 코드가 ajax 요청 후에 작동하는 것을 확인하는 것이 즐거웠다. first-project에서 프론트엔드를 맡으면서 CSS가 부족했는데 그 부분을 조금이나마 더 공부할 수 있어서 또 좋았다. 한편으로는 react의 단방향 데이터 플로우에 대해서는 더 많은 이해가 필요하겠다는 생각을 했다. SPA라는 이름에 더욱 걸맞게 새로고침 없이 렌더될 수 있을텐데. CSS로 퍼즐이 맞춰질 때 애니메이션도 적용하고 싶다. 모바일 대응까진 아니더라도 미디어 쿼리로 반응형도 구현하고 싶다. 기타 등등 개선의 여지가 많이 남아있다고 생각하며 리팩토링을 마무리 하였다.</p>
<h3 id="마무리-느낀점">&lt;마무리: 느낀점&gt;</h3>
<p>∘ 나는 프론트엔드로서 작업을 하면서 <strong>프론트엔드에 대해 새로운 관심</strong>이 생겼다. 나는 final-project를 마무리할 당시까지만 해도 백엔드 개발자로서 구직을 하려고 계획했었다.  데이터를 다루고 저장하는 기능은 백엔드의 역할이고 그게 실제 기능을 구현하는 것이라고 (엄밀한 근거는 없이) 생각했기 때문이다. 하지만 리팩토링 과정 중에 역으로 API 서버를 실제 view에 구현하는 게 아주 매력적인 작업이라는 것을 알게 되었다. </p>
<p>∘ 코드스테이츠에서 기초적인 javascript 문법을 배우고, react, node.js 등을 차근차근 배우면서도 이것으로 뭘 만들 수 있는 걸까라는 질문을 항상 해왔었다. 전체 그림이 보이지 않았다. 하지만 파이널 프로젝트와 리팩토링을 하면서, 배운 것들을 어떻게 활용되는지 알 수 있었다.   </p>
<p>∘ 또 한가지 느낀 점은 커뮤니케이션에 관한 점이다. 개발자는 협업을 해야하기 때문에 좋은 커뮤니케이션 능력을 함양해야 한다고 말로만 들었었는데, 실제 프로젝트를 진행하면서 알게된 점은, 그 말이 <strong>&#39;커뮤니케이션은 어렵다&#39;</strong> 는 것이다. 나의 생각이 팀원 분들에게 손쉽게 그리고 온전하게 전해지지 않고 그 반대도 마찬가지였다. &quot;프론트엔드 분들이 더 활용하기 쉽게 API 문서를 어떻게 더 전달력있게 작성했으면 좋았을걸&quot;, &quot;기획 단계에서 더 많이 고민을 했었으면 구현 단계에서 더 수월했을텐데&quot;이라는 생각을 리팩토링을 진행하면서 계속 했었다. 커뮤니케이션은 어렵기 때문에, 내가 생각하는 것보다 훨씬 더 많은 공을 들여야한다는 것을 알았다. 또 git workflow나 네이밍컨벤션의 목적, 깔끔한 코드를 구사해야하는 이유 등에 대한 고민이 바로 그런 노력의 일환이라고 생각했다.</p>
<p><img src="https://images.velog.io/images/ys_sung/post/b874bcf8-776a-4ec0-8df6-37b0c6f62f26/%EA%B8%B0%EB%8A%A5%ED%94%8C%EB%A1%9C%EC%9A%B02.png" alt=""><em>(프로젝트를 진행해나가면서 간략해진 기능 플로우, 처음 계획한 의도대로 일이 흘러가지 않았다)</em></p>
<p>∘ 프로젝트를 진행하면서 해결해야하는 문제에 맞딱뜨렸을 때 나는 항상 다음과 같이 생각하려고 애를 썼다 </p>
<blockquote>
<p>_ 지금 이 문제를 해결하는 방법은 분명하게 있다. 어쩌면 단 몇줄의 코드만 치면 해결될 문제일 수도 있다. 그리고 그 단 몇줄의 솔루션을 찾는 과정은 분명 도전적이지만 그만큼 흥미롭기도 한 일이다!_ </p>
</blockquote>
<p>∘ 이런 생각을 가지고 앞으로 꾸준히 발전해서 문제해결능력을 갖추고 같이 일하기도 좋은 개발자가 되고 싶다.</p>
<p> 감사합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[node.js의 트랜잭션 문서 정리]]></title>
            <link>https://velog.io/@ys_sung/node.js%EC%9D%98-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EB%AC%B8%EC%84%9C-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@ys_sung/node.js%EC%9D%98-%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98-%EB%AC%B8%EC%84%9C-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Wed, 04 Nov 2020 13:19:59 GMT</pubDate>
            <description><![CDATA[<h1 id="nodejs의-트랜잭션-문서-정리">node.js의 트랜잭션 문서 정리</h1>
<p>HTTP 트랜젝션 문서를 개인적인 학습목적으로 정리함.</p>
<p>원문: <a href="https://nodejs.org/ko/docs/guides/anatomy-of-an-http-transaction/">https://nodejs.org/ko/docs/guides/anatomy-of-an-http-transaction/</a></p>
<hr>
<ul>
<li><p>서버 만들고 포트에 연결</p>
<pre><code class="language-jsx">  const http = require(&#39;http&#39;);

  const server = http.createServer((request, response) =&gt; {
    // 여기서 작업이 진행됩니다!
  });

  server.listen(PORT, ip, () =&gt; {
     //
  })</code></pre>
<hr>
</li>
</ul>
<h3 id="request-객체">&lt;request 객체&gt;</h3>
<ul>
<li><p>request 객체에는 유용한 프로퍼티들이 있다</p>
<ul>
<li>request.method</li>
<li>request.url (전체 url에서 서버, 프로토콜, 포트를 제외한 것, ex) /upper )</li>
<li>request.header</li>
</ul>
</li>
<li><p>그렇다면 request.body도 있을까? ⇒ x</p>
<ul>
<li><p>buffer/ stream이란? 데이터를 전달할때 버퍼형식으로 전달하고 효율을 위해 잘게 쪼개는데 그 방식이 스트림이다</p>
<pre><code class="language-jsx">let body = [];
request.on(&#39;data&#39;, (chunk) =&gt; {
body.push(chunk);
}).on(&#39;end&#39;, () =&gt; {
body = Buffer.concat(body).toString();
})

//여기서 chunk는 데이터를 잘게 쪼갠 단위이다
//데이터를 스트림으로 받아와서 배열에 푸시한 다음
//Buffer.concat으로 다시 하나의 요소로 합쳐서 읽을수 있게 toString()했다

//이렇게 코드를 쓰지 않고 더 간단한 방법이 있는 것 같다
//어떤 일이 일어나는지 이해하기 위한 코드인듯</code></pre>
</li>
</ul>
</li>
<li><p>오류에 대한 이벤트리스너도 등록해야 한다(에러 핸들링)</p>
<pre><code class="language-jsx">  request.on(&#39;error&#39;, (err) =&gt; {
      //오류가 발생하면 error 이벤트 발생하고
      //여기에서 처리 코드 써넣어야
    console.err(error)
  })</code></pre>
<hr>
</li>
</ul>
<h3 id="response-객체">&lt;Response 객체&gt;</h3>
<ul>
<li><p>상태코드 설정 → 헤더 설정 → 바디 전송</p>
</li>
<li><p>상태코드 설정</p>
<pre><code class="language-jsx">  reponse.statusCode = 404
  //숫자는 http 상태코드
  //기본값은 200(성공응답)</code></pre>
<ul>
<li>상태코드 <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Status">https://developer.mozilla.org/ko/docs/Web/HTTP/Status</a><ul>
<li>100번대 : 정보응답</li>
<li>200번대 : 성공응답</li>
<li>300번대 : 리다이렉션(URI 변경)</li>
<li>400번대 : 클라이언트 에러</li>
<li>500번대 : 서버에러</li>
</ul>
</li>
</ul>
</li>
<li><p>응답헤더 설정&lt; response.setHeader() 방식 &gt;</p>
<pre><code class="language-jsx">  response.setHeader(&#39;Content-Type&#39;, &#39;application/json&#39;);
  response.setHeader(&#39;X-Powered-By&#39;, &#39;bacon&#39;);

  //&#39;Content-Type&#39; : 응답으로 반환된 컨텐츠의 데이터타입 설정
    //텍스트 : &quot;text/html; charset=utf-8&quot;
    //JSON 객체 : &quot;application/json&quot;
      //다른 것들엔 뭐가 있을까?</code></pre>
<ul>
<li><p>헤더 유형 ( &quot; Content-Type &quot; )</p>
<p>  <a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Headers">https://developer.mozilla.org/ko/docs/Web/HTTP/Headers</a></p>
</li>
</ul>
</li>
<li><p>더 명시적인 방식으로 헤더 설정도 가능하다&lt; response.writeHead() &gt;</p>
<ul>
<li><p>암묵적인 헤더? 명시적인 헤더?</p>
<pre><code class="language-jsx">response.writeHead(200, {
&#39;Content-Type&#39;: &#39;application/json&#39;,
&#39;X-Powered-By&#39;: &#39;bacon&#39;
});
//첫번째 인자에 상태코드</code></pre>
</li>
</ul>
</li>
<li><p>응답 바디 전송&lt; response.write() &gt;</p>
<pre><code class="language-jsx">  response.write(&#39;&lt;html&gt;&#39;);
  response.write(&#39;&lt;body&gt;&#39;);
  response.write(&#39;&lt;h1&gt;Hello, World!&lt;/h1&gt;&#39;);
  response.write(&#39;&lt;/body&gt;&#39;);
  response.write(&#39;&lt;/html&gt;&#39;);
  response.end();

  //요청 전송이 끝날 때 response.end()
  //response.end(&#39;&lt;html&gt;&lt;body&gt;&lt;h1&gt;Hello, World!&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;&#39;);로도 작성 가능
</code></pre>
<ul>
<li>바디 전송 전에 헤더부터 설정해야 하는 것에 유의</li>
</ul>
</li>
<li><p>응답도 에러핸들링 해줘야 한다</p>
</li>
</ul>
<hr>
<h3 id="예제">&lt;예제&gt;</h3>
<ul>
<li><p>클라이언트가 보낸 요청을 그대로 응답하는 서버</p>
<pre><code class="language-jsx">  const http = require(&#39;http&#39;);

  http.createServer((request, response) =&gt; {
    const { headers, method, url } = request;
    let body = [];
    request.on(&#39;error&#39;, (err) =&gt; {
      console.error(err);
    }).on(&#39;data&#39;, (chunk) =&gt; {
      body.push(chunk);
    }).on(&#39;end&#39;, () =&gt; {
      body = Buffer.concat(body).toString();

      response.on(&#39;error&#39;, (err) =&gt; {
        console.error(err);
      });
  //응답의 에러는 end 이벤트의 콜백 안에서 처리하는구나

      response.statusCode = 200;
      response.setHeader(&#39;Content-Type&#39;, &#39;application/json&#39;);
      // response.writeHead(200, {&#39;Content-Type&#39;: &#39;application/json&#39;})

      //headers, method, url, &#39;body&#39; 프로퍼티가 있는 객체를 할당
      const responseBody = { headers, method, url, body }; 

      //JSON 객체로 변환해서 응답 body 전송
      response.write(JSON.stringify(responseBody));
      response.end();
      // response.end(JSON.stringify(responseBody)) 도 가능

    });
  }).listen(8080);</code></pre>
</li>
<li><p>위 서버에 조건 추가</p>
<ul>
<li>요청 메서드 POST</li>
<li>URL /echo</li>
</ul>
</li>
</ul>
<pre><code class="language-jsx">const http = require(&#39;http&#39;);

http.createServer((request, response) =&gt; {
  if (request.method === &#39;POST&#39; &amp;&amp; request.url === &#39;/echo&#39;) {
    let body = [];
    request.on(&#39;data&#39;, (chunk) =&gt; {
      body.push(chunk);
    }).on(&#39;end&#39;, () =&gt; {
      body = Buffer.concat(body).toString();
      response.end(body);
    });
  } else {
    response.statusCode = 404;
    response.end();
  }
}).listen(8080);

//간단한 조건문으로 메소드와 URL에 따라 다른 응답을 할 수 있다
  //조건에 맞으면(&#39;POST&#39;, /echo) 요청을 그대로 응답
  //조건에 맞지 않으면 클라이언트 에러
//URL에 따른 분기: 라우팅
//express 프레임워크로 라우팅하는 방법도 학습</code></pre>
<ul>
<li>pipe 사용 (위 코드를 간략하게 작성할 수 있다)</li>
</ul>
<pre><code class="language-jsx">const http = require(&#39;http&#39;);

http.createServer((request, response) =&gt; {
  if (request.method === &#39;POST&#39; &amp;&amp; request.url === &#39;/echo&#39;) {
    request.pipe(response);
  } else {
    response.statusCode = 404;
    response.end();
  }
}).listen(8080);

//객체(여기서는 request 객체) .pipe (객체, 여기서는 response 객체)</code></pre>
<ul>
<li><p>stderr(Standard error) / stdout(Standard output)에 오류 로깅</p>
<ul>
<li><p>stdout?</p>
</li>
<li><p>stderr?</p>
</li>
<li><p>에러 문서 : <a href="https://nodejs.org/api/errors.html">https://nodejs.org/api/errors.html</a></p>
<pre><code class="language-jsx">const http = require(&#39;http&#39;);

http.createServer((request, response) =&gt; {
request.on(&#39;error&#39;, (err) =&gt; {
  console.error(err);
//이 부분이 중요한 듯, 요청에 오류가 있을 때 오류코드 &#39;응답&#39;
  response.statusCode = 400;
  response.end();
});

//응답에 오류가 있을 때 그 에러 콘솔에 표시
response.on(&#39;error&#39;, (err) =&gt; {
  console.error(err);
});

if (request.method === &#39;POST&#39; &amp;&amp; request.url === &#39;/echo&#39;) {
  request.pipe(response);
} else {
//조건이 맞지 않을 때 오류코드 설정하고 응답(라우팅)
  response.statusCode = 404;
  response.end();
}
}).listen(8080);</code></pre>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="정리">&lt;정리&gt;</h3>
<p>문서를 읽었으면 다음 질문에 답할 수 있어야 한다</p>
<ul>
<li>요청 핸들러 함수로 HTTP 서버의 인스턴스를 생성하고 특정 포트로 서버를 열 수 있습니다.<ul>
<li>ok</li>
</ul>
</li>
<li>request 객체에서 헤더, URL, 메서드, 바디 데이터를 가져올 수 있습니다.<ul>
<li>request.url / request.method 등, 구조분해할당 사용하면 더 편함</li>
</ul>
</li>
<li>URL이나 request 객체의 데이터에 기반을 둬서 라우팅을 할 수 있습니다.<ul>
<li>조건문으로 분기.</li>
</ul>
</li>
<li>response 객체로 헤더, HTTP 상태 코드, 바디 데이터를 보낼 수 있습니다.<ul>
<li>statusCode(), setHeader(), writeHead(), wirte()</li>
</ul>
</li>
<li>request 객체에서 response 객체로 데이터를 파이프로 연결할 수 있습니다.<ul>
<li>request객체.pipe(response객체)</li>
</ul>
</li>
<li>request와 response 스트림 모두에서 스트림 오류를 처리할 수 있습니다.<ul>
<li>아직 애매하다. 예제 참고하며 학습</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[S3, EC2, RDS]]></title>
            <link>https://velog.io/@ys_sung/S3-EC2-RDS%EB%A5%BC-%EA%B0%81%EA%B0%81-%EC%A1%B0%EC%82%AC</link>
            <guid>https://velog.io/@ys_sung/S3-EC2-RDS%EB%A5%BC-%EA%B0%81%EA%B0%81-%EC%A1%B0%EC%82%AC</guid>
            <pubDate>Tue, 03 Nov 2020 05:28:48 GMT</pubDate>
            <description><![CDATA[<h3 id="intro-deployment">Intro Deployment</h3>
<ul>
<li>deployment란 무엇인가?<ul>
<li>내 코드를 다른 컴퓨터 위에서 돌려서, 그 서비스, 서버, 클라이언트에 우리의 고객들이 접속할 수 있게 하는 것</li>
<li>내 컴퓨터에서 했던 것처럼 npm install을 하거나 package.json을 확인하는 방법과는 다르다</li>
<li>노드 버전도 모르고, dependencies도 모르는 등 배포환경에 대한 정보는 제한적</li>
<li>실제 production이 배포되는 과정은 생각보다 복잡하다<ul>
<li>크게 4단계로 나뉜다: development, integration, staging, production</li>
</ul>
<ol>
<li>development: 실제 개발단계, 지금까지 배운 것들, 코드쓰고 테스트하는 것을 로컬에서</li>
<li>integration: 원래 있던 서비스와 충돌하진 않는지, 팀원과 코드를 합쳤을 때 충돌하지 않는지, 지금만든 기능이 다른 기능을 침범하지 않는지를 확인하는 과정</li>
<li>staging: 합쳐진 코드를 배포환경과 가장 유사한 단계에서 다시 한번 테스트(일종의 준배포)</li>
<li>production: 실제 배포 </li>
</ol>
</li>
<li>배포된 서비스는 노드버전, dependencies, port number, hostname, urls and file paths, api keys 등이 잘 설정되어야 한다(ex-경로를 절대주소로 쓰지 말것 / package.json에 필요한 dependencies를 잘 명기할 것)</li>
<li>배포 플랫폼: 스프린트에선 AWS 활용</li>
</ul>
</li>
</ul>
<hr>
<h3 id="intro-deploy-strategy">Intro Deploy Strategy</h3>
<ol>
<li>싱글페이지 앱을 static serve하기 위한 전략(SPA serve strategy)</li>
</ol>
<ul>
<li>리액트 : build 스크립트를 사용해서 수많은 js를 하나로 포장<ul>
<li>이 파일을 어떻게 serve?<ul>
<li>build 파일 서브를 위한 cloud : <strong>Amazon S3</strong>(스프린트에서 활용)<ul>
<li>앱스토어에서 앱을 다운 받는 형식과 유사</li>
<li>S3의 버킷주소는 파일을 담을 수 있는 주소</li>
<li>그 주소에서 js, html, css 파일을 다운로드</li>
</ul>
</li>
<li>node.js + Express의 static file serve 활용</li>
</ul>
</li>
</ul>
</li>
</ul>
<ol start="2">
<li>API를 요청할 수 있는 서버애플리케이션을 배포하는 전략(Server Application deploy strategy)</li>
</ol>
<ul>
<li>로컬에서 작업할 때는 리액트 → localhost:xxxx <a href="http://localhost:3000/"></a> // node.js → localhost:yyyy</li>
<li><em>But</em> ****외부인이 내컴퓨터에게 들어오게 해서는 안된다.</li>
<li>외부 컴퓨터를 빌려야 한다 → <strong>Amazon EC2</strong></li>
<li>Amazon EC2에 있는 컴퓨터에 노드 설치하고 그 위에 서버 애플리케이션을 올려서 구동</li>
<li>Amazon EC2란? 원격접속할 수 있는 컴퓨터 가상머신(그냥 다른 컴퓨터)<ul>
<li>실제로 아이피가 있고, 그 주소를 할당받은 것</li>
</ul>
</li>
</ul>
<ol start="3">
<li>데이터베이스</li>
</ol>
<ul>
<li><strong>AWS RDS</strong> 서비스 활용(데이터베이스 설정의 고된 과정을 거치지 않기 위함)</li>
</ul>
<hr>
<h3 id="deploy-sprint-architecture">Deploy Sprint Architecture</h3>
<p> 1.Bare minimum(스프린트 수준)</p>
<ul>
<li>리액트 —  노드(+익스프레스) — MySQL</li>
<li>우리의 전략 :<ol>
<li>리액트는 static file을 제공하는 클라우드 서비스(<em>S3</em>)를 사용해서 리액트 빌드파일을 서브하는 버켓 셋업</li>
<li>그 버켓에서 클라이언트 애플리케이션을 받아간 유저가 접속할 수 있는 <em>EC2</em> <strong>구축</strong></li>
<li>EC2에 있는 노드 어플리케이션이 배포된 데이터베이스에 접속할 수 있도록 <strong>설정(</strong>요청을 할 때 필요한 데이터는 <em>RDS</em> ****라고 하는 데이터베이스 인스턴스에서 쿼리함)</li>
</ol>
</li>
</ul>
<ol start="2">
<li>Advanced</li>
</ol>
<ul>
<li>큰 틀에선 변함없지만, https라고 하는 웹사이트를 만들기 위한 무언가를 해야함</li>
<li>이 스프린트에서 하긴 어렵지만, 프로젝트 진행하면서는 한번 시도해볼만함</li>
<li>복잡한 얘기(나중에 필기)</li>
</ul>
<ol start="3">
<li>Nightmare</li>
</ol>
<ul>
<li>이게 뭐야..(나중에 필기)</li>
<li>프로젝트 때에도 구축하기 어려울 수도</li>
<li>있다는 것을 아는 것은 좋다</li>
<li>배포의 세계도 어렵구나</li>
</ul>
<hr>
<h3 id="study-aws-with-pair">Study AWS with Pair</h3>
<ul>
<li><p>S3, EC2, RDS를 각각 조사한다</p>
<ul>
<li><p><strong>S3(Simple Storage Service)</strong> :  핵심개념 → <em>버킷</em>,</p>
<ul>
<li>파일 서버 역할을 하는 서비스 → 트래픽 같은 문제를 걱정하지 않아도 된다</li>
<li>인터넷을 위한 저장공간. 웹 어디에서든 데이터를 저장하고 다시 꺼내올 수 있다. <strong>AWS management</strong> 콘솔을 이용해서 기능들을 사용할 수 있다.</li>
<li>파일을 저장하려면 버킷에 그것을 객체의 형태로 업로드해야 한다</li>
<li>버킷이란: 객체를 담는 그릇. 하나 또는 그 이상의 버킷을 만들 수 있다. 객체형태의 파일을 그룹핑한다.  각각의 버킷에 접근권한을 설정할 수도 있다.</li>
<li><a href="https://docs.aws.amazon.com/AmazonS3/latest/gsg/GetStartedWithS3.html">https://docs.aws.amazon.com/AmazonS3/latest/gsg/GetStartedWithS3.html</a> 가이드문서</li>
</ul>
</li>
<li><p><strong>EC2(Amazon Elastic Compute Cloud)</strong> :  핵심개념 → <em>이미지</em></p>
<ul>
<li><em>&#39;안전하고 크기 조정이 가능한 컴퓨팅 용량을 클라우드에서 제공하는 웹 서비스입니다.&#39;</em></li>
<li>클라우드 컴퓨터 : 직접 물리적인 서버 시설을 갖추기보다 인터넷으로 접근해서 사용할 수 있는 서버, 가상의 컴퓨터를 빌리는 것,</li>
<li>이미지(아마존 머신 이미지): EC2는 이미지에 실제 컴퓨터처럼 프로그램을 깔 수도 있고 파일을 저장할 수도 있는데 그 기능을 제공하는 것? 이미지를 사용해서 애플리케이션, 라이브러리, 데이터 등의 설정을 한다.</li>
<li><a href="https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/concepts.html">https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/concepts.html</a> 가이드문서</li>
</ul>
</li>
<li><p><strong>RDS(Amazon Relational Database)</strong> : 핵심개념 → <em>DB 인스턴스</em></p>
<ul>
<li>관계형 데이터베이스를 설치, 운영, 확장할 수 있는 서비스</li>
<li>용량을 제공하고 공통적인 데이터베이스 작업을 관리한다<ul>
<li>백업, 소프트웨어 패치, 장애감지 등의 기능</li>
<li><strong>MySQL</strong>, MariaDB, PostgreSQL, Oracle 및 Microsoft SQL Server 같은 데이터베이스 제품을 사용</li>
<li>DB 인스턴스 : DB 인스턴스 안에 사용자가 만든 여러 데이터베이스가 포함된다</li>
<li>AWS Command Line Interface / Amazon RDS API / <strong>AWS Management</strong> 콘솔을 사용해 DB 인스턴스를 생성하고 수정 가능</li>
</ul>
</li>
<li><a href="https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/Welcome.html">https://docs.aws.amazon.com/ko_kr/AmazonRDS/latest/UserGuide/Welcome.html</a> 가이드문서</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="practice-deploy-shortly-express-to-cloud">Practice Deploy &#39;Shortly Express&#39; to Cloud</h3>
<ol>
<li>Client - Shortly Express React Client 빌드 파일을 S3에 배포 한다.</li>
<li>Server Application - Shortly Express API server application을 EC2에 올려서 구동한다.</li>
<li>Database - 로컬 mysql을 RDS로 대체하여, server application과 연결 한다.</li>
</ol>
<hr>
<h3 id="react-build">React Build</h3>
<ul>
<li>아마존 S3 버켓에 리액트 앱을 빌드해서 배포하는 과정<ul>
<li><del>배포할 간단한 리액트 앱 만들기</del></li>
<li>이렇게 만든 앱을 퍼블릭링크, 즉 배포하는 것이 목적 → <strong>&#39;npm run build&#39;</strong></li>
</ul>
</li>
</ul>
<h3 id="create-bucket">Create Bucket</h3>
<ul>
<li><p>AWS Management Console에 접속</p>
</li>
<li><p>S3 검색해서 들어가기 → 버킷만들기</p>
</li>
<li><p>설정 :</p>
<ul>
<li>속성 → 정적 웹사이트 호스팅 → 인덱스 문서, 에러문서 설정</li>
<li>주어진 엔드포인트로 접속 → 404 forbidden! (프라이빗 버킷이기 때문)</li>
<li>누구나 접속할 수 있게  <strong>PUBLIC</strong> 권한설정 해주어야 한다<ul>
<li>권한 → 퍼블릭 엑세스 차단 해제</li>
<li>버킷정책 → 정책 생성기 →s3 bucket policy →정책생성후 복붙<ul>
<li>principal : 문서참고</li>
<li>ARN : 문서참고(내가 만든 이름과 일치해야함)</li>
<li>파일 올릴 때 build폴더 통째로가 아니라 안의 내용물을 복붙해야함</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
</li>
</ul>
<h3 id="create-server-application">Create Server Application</h3>
<ul>
<li><p>간단한 노드 서버 애플리케이션 만들기</p>
<ul>
<li><p>express 프레임워크 사용 npm init → npm install express --save</p>
</li>
<li><p>index.js 파일 안에 서버코드 작성 → <a href="http://localhost:5000">localhost:5000</a> 들어가면 문자 뜬다</p>
<pre><code class="language-jsx">  const express = require(&#39;express&#39;);

  const app = express();

  app.use(&#39;/&#39;, (req, res) =&gt; {
      res.send(&#39;hello practice node server-deploy&#39;)
  })
  app.listen(5000, () =&gt; {
      console.log(&#39;server on 5000&#39;);
  })</code></pre>
</li>
<li><p>우리 목적은 로컬호스트가 아니라 배포된 url에서 작동해야 한다</p>
</li>
<li><p>아마존 컴퓨터는 usb 같은 장치를 꽂을 수 없기 때문에 깃허브 원격저장소를 통해서 index.js파일을 EC2에 업로드해야 한다</p>
</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[개발자가 되고 싶어 <코드스테이츠 PRE 과정 회고>]]></title>
            <link>https://velog.io/@ys_sung/%EC%BD%94%EB%93%9C-%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%B8%A0-PRE-%EC%BD%94%EC%8A%A4%EB%A5%BC-%EB%90%98%EB%8F%8C%EC%95%84%EB%B3%B4%EB%A9%B0</link>
            <guid>https://velog.io/@ys_sung/%EC%BD%94%EB%93%9C-%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%B8%A0-PRE-%EC%BD%94%EC%8A%A4%EB%A5%BC-%EB%90%98%EB%8F%8C%EC%95%84%EB%B3%B4%EB%A9%B0</guid>
            <pubDate>Sun, 30 Aug 2020 23:22:32 GMT</pubDate>
            <description><![CDATA[<p>  *<em>모든 과제와 HA 문제를 다 풀고 PRE 코스가 끝났다. 한달은 짧은 기간이지만 과정을 따라가다보니 어느새 꽤 많은 것을 학습한 것 같다. 적어도 한달 전엔 나는 코딩에 대해서, 자바스크립트의 기초적인 문법에 대해서, 어떤 식으로 깃허브에 푸시하는지, 테스트주도개발이나 재귀 등의 개념이 무엇인지에 대해서 아는 것이 하나도 없었던 것에 비교하면 말이다. Immersive 과정에 들어가기 전에 간략하게나마 회고 글을 작성해본다. *</em> 
<br> </br></p>
<ul>
<li><p><strong>학습과정</strong></p>
</li>
<li><p>PRE 과정에서 배운 것들은 코플릿의 문제들을 풀면서 javascript의 기본 문법, 고차함수, 알고리즘, 재귀 등을 학습했고, 여러 스프린트를 통해서 유닛테스트, 테스트 주도 개발, DOM, 고차함수가 작동하는 방식에 대해서 조금 더 알 수 있었다. <strong><em>전체적으로 동적으로 작동하는 웹페이지를 만드는 과정을 대략적으로나마 체험한 것 같았다</em>.</strong></p>
</li>
<li><p>가장 흥미로웠던 스프린트는 트위틀러였다. 아마 직접 눈에 보이는 페이지를 만들고 심지어 그게 작동도 하기 때문이 아닐까 싶었다. 페어 프로그래밍으로 트위틀러를 진행할 때, 페어 분은 정규 학습시간 동안 뚝딱뚝딱 완성하셨는데 나는 그것의 몇배나 더 많은 시간을 투자해야 해서 주눅이 들기도 했다. 하지만 학습을 시작할 때 &#39;내가 잘해낼 것이라고 생각하지 말자. 분명히 나는 잘 안돼서 좌절감을 느낄 거고 그것을 자연스러운 과정이라고 생각하자&#39;라고 다짐한 것을 되새기고, 완벽하지 않은 학습이지만 놓지 않고 계속 이어가려고 했다. 그렇게 해서 트윗 작성자를 눌러 작성한 트윗을 필터링하는 기능까지 적용하니 무척 뿌듯했다. 코드 스테이츠의 일정을 충실하게 따라가는 범위 안에서 <strong>스스로의 페이스가 어떤지 찾아내고 유지하는 것이 앞으로의 16주 동안의 여정을 완주하기에 중요하겠다는 생각이 들었다.</strong></p>
</li>
</ul>
<p><br></br></p>
<ul>
<li><p><strong>Pair Programming</strong> 
-페어 프로그래밍은 처음에는 낯설고 어색한 느낌이 들었다. 모르는 동기 분과 역할을 나누어서 주어진 문제를 해결해야 하는 것이 특히 그랬었고, 이렇게 과제를 수행하는 것이 어떤 도움을 주는 것인지 알 수가 없었다. 하지만 나는 코플릿의 문제들은 아주 만족스러웠고, 그래서 페어 프로그래밍도 믿고 따라가다보면 어떤 도움을 주는지 알 수 있을 것이라 생각했다. </p>
<p>-내 경우에는 앞에 다른 분이 있으면 먼저 당황하는 게 가장 큰 문제였다. 혼자서 차분하게 집중했더라면 시간이 걸릴지라도 풀 수 있었을 문제를 페어 프로그래밍 상황에서는 더욱 버벅거리게 되는 것이다. 특히 거의 모든 페어 분들이 나보다 잘하는 분이라서 더욱 그랬었던 것 같다. 물론 스스로 이런 성격이라는 것은 알고 있었지만, 페어 프로그래밍을 진행하는 내내 나의 이런 성격을 크게 느낄 수 있었다. 내가 개발자로 일할 때 그런 상황에서 <strong>침착하게 문제를 해결하는 능력</strong>을 반드시 갖추어야 할 것이다.</p>
<p>-페어 프로그래밍의 가장 큰 효용은, 바로 그 능력을 기르는 것을 연습하는 과정이기도 하다고 생각했다. 어쨌든 개발자는 협업해서 일을 하는 사람들(사실 대부분의 일이 그렇다)이고, <strong>soft skill을 기르는 것이 문법이나 업무에 필요한 여러 개념들을 이해하고 실제로 적용할 수 있는 능력을 기르는 것 만큼이나 중요하다는 걸 알 수 있었다.</strong></p>
<p><br></br></p>
</li>
<li><p><strong>Hiring Assessment</strong>
-코플릿으로 주어진 문제들 푸는 것은 그래도 해 본 것이라 익숙했지만, 레퍼런스를 전혀 확인할 수 없고 어쨌든 스스로의 힘으로 문제를 풀어야 했다. 코플릿으로 DOM 문제도 나오는 등, 한달동안 공부한 것들을 얼마나 숙지했는지 스스로 확인할 수 있는 기회였다. 내 경우에는, 한달 동안 공부를 하면서 밀린 과제들을 솔로위크 동안 처리할 수 있는 시간이기도 했다. 이전의 코플릿 문제들이 그랬던 것처럼, HA 문제들도 쉬운 것들도 있었고 어려운 문제도 있었다. 특히 5번 문제와 6번 문제를 풀었을 때, 코플릿의 테스트를 초록색으로 다 채웠을 때 기분은 아주 좋았다. 내가 한달동안 허투루 공부하지는 않았구나, 개발자가 되고 싶다 등의 생각을 했었던 것 같다. <em>마지막 7번 문제를 힌트 없이 스스로 풀어냈으면 더욱 좋았을텐데.</em></p>
<p><br></br></p>
</li>
<li><p><strong>부족한 점 / 아쉬웠던 점</strong>
-<strong>&lt;헬프데스크를 적극적으로 이용하지 않은 점&gt;</strong> PRE 코스 초반에 일부러 질문해야겠다고 메모까지 해놓고 질문했던 단 한 번을 제외하면 과정 내내 헬프데스크를 이용하지 않았다. 스스로 문제를 해결하겠다는 고집도 있었고, 질문 자체가 두려웠던 이유도 있었다. 질문 글을 쓰는 것 자체가 생각보다 많은 노력이 필요한 일이기도 했고. 하지만 그 노력 자체가 학습하는 과정이었을텐데, 그 점은 반성해야겠다고 생각했다. 나는 일부러 질문해야겠다고 딱 정해두지 않으면 질문을 하지 않는 성향이기 때문에 <strong>일주일에 한 번은 질문을 만들어서라도 하겠다는 규칙</strong>을 정했다. 주말에 질문하는 시간을 따로 정해두면 좋을 것 같다.</p>
<p>-<strong>&lt;스스로 문제를 해결하겠다는 고집을 부린 점&gt;</strong>  물론 문제를 해결하겠다는 의지 자체는 좋지만 문제는 그것이 비효율적인 학습으로 이어진다는 것이다. 코플릿 문제 하나를 가지고 두시간, 세시간 고민하는 것 같이 말이다. 나는 그런 고집의 결과로 솔로위크가 다가왔을 때는 HA 뿐만이 아니라 밀린 과제들을 해결하느라 고생했다. Immersive 때는 과제가 끝나는 당일에 1차 제출을 해야하는 모양인데, 계속 이렇게 비효율적인 방식으로는 마감을 제대로 마칠 수 없을 것이다. 게다가 코플릿 문제를 풀다가 결국에 레퍼런스를 확인했다고 하더라도 이후에 그 문제를 풀어보면 이전보다 더 나아졌다는 것을 알 수 있었다. <strong>충분히 고민하되 도움을 요청하는 것을 망설이지 말 것.</strong> 그러기 위해 헬프데스크가, 오피스아워가 있는 것이다. </p>
<p>-<strong>&lt;시간관리&gt;</strong> 여러 스프린트를 진행하면서, 특히 underbar를 진행할 때쯤에는 정말 허덕이면서 과정을 따라간 것 같다. 의욕이 너무 앞서서 밤낮을 뒤바꾸면, 다음날은 더 많은 피로가 찾아왔다. 이번 한달은 어떻게 버텨왔지만 아무리 생각해도 네 달동안 이 짓을 반복할 수 없다. 코스 회고 시간에 나온 것처럼 차라리 일찍 일어나서 공부하는 것이 낫다.** 남들이 깨어있는 동안에 나도 깨어있고, 그 동안에 정말 집중하자.**</p>
<p>-<strong>&lt;모각코에 적극적으로 참여하지 않은 점&gt;</strong> 적극적으로 참여하지 않은 이유는 헬프데스크를 많이 이용하지 않은 이유와 같다. 하지만 모각코는 질문보다 덜 부담스러웠고, 정규학습 시간 이후의 학습을 효율적으로 만드는 데에 많은 도움이 됐을텐데 그것이 아쉽다. 코드스테이츠에 지원서를 넣을 때 더이상 망설이지 않겠다고 써넣은 게 부끄러웠다. <strong>필요하다면, 그냥 하자.</strong></p>
<p><br></br></p>
</li>
</ul>
<p><strong>이제 Immersive 과정의 시작이다. 한달 전에 PRE 코스를 시작할 때에 아무 것도 아는 것이 없었기 때문에 스스로 할 수 있을지에 대한 의구심으로 가득 차 있었다. 그렇다면 지금은 스스로에 대한 확신으로 가득 차있는가? 절대 그렇지 않다. 하지만 한달동안 열심히 했고, 어쨌든 Immersive 과정에 합류하게 됐다. 나는 나의 이 작은 성취를 바탕으로 앞으로의 16주 동안 더 많은 것을 배우고 개발자로 거듭날 수 있기를 바란다. <em>개발자가 되고 싶어!</em></strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[200806_TIL]]></title>
            <link>https://velog.io/@ys_sung/200806TIL-daoo9vuu</link>
            <guid>https://velog.io/@ys_sung/200806TIL-daoo9vuu</guid>
            <pubDate>Thu, 06 Aug 2020 16:38:27 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p><strong>Pair로 테스트빌더 과제를 함께 수행했다.</strong> 코드를 짜기 전에 mocha라는 프레임워크를 사용해서 유닛테스트와 내가 직접 짠 함수를 비교해보고 통과시키는 등의 작업을 했다. 마치 대청소를 하는데, 욕실청소, 설겆이, 바닥쓸기 등으로 작업을 세분화하고 체크리스트를 만들어 하나씩 확인하며 일을 햬내는 것 같은 느낌이 들었다. 강의에 나온 레고 비유처럼 작은 단위부터 쌓아나가서 큰 모양을 만드는 방법론이라고 이해했다. 기본 과제의 마지막인 step3에서 직접 유닛테스트 함수를 작성하는 부분에서 많이 헤멨다.</p>
</li>
<li><p><strong>소크라티브 솔루션 시간에 줌으로 스코프와 클로저의 개념에 대해서 배웠다.</strong> 소크라티브 문제를 많이 틀렸는데 해설을 듣고 함수를 실행한 이후에 어떤 순서로 외부함수와 내부함수가 작동하는지 조금 더 알 수 있게 되었다.(<em>복습이 필요하다.</em>) 내부 함수에서 외부함수에 있는 변수명과 이름은 같지만 별개의 변수를 선언하는 것과, 내부함수에 변수를 할당해서 외부함수에 있는 변수의 값에 영향을 주는 것이 다르다는 것을 배웠다.</p>
</li>
<li><p>_새로운 페어 분이랑 처음 과제를 수행한 날이다. 페어 분이 정규 수업 시간에 테스트빌더 과제를 뚝딱뚝딱 해내는 것을 보니 신기했다. 내가 겨우 과제를 수행해서 제출하니 새벽 1시인데.. 하지만 자바스크립트 언어의 다양한 개념들과, 어떤 방식으로 일하는지(github에 커밋하는 법, 테스트 주도 개발 등) 등의 새로운 것들을 배우는 것이 즐겁기도 하다. _</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[200805_TIL]]></title>
            <link>https://velog.io/@ys_sung/200806TIL</link>
            <guid>https://velog.io/@ys_sung/200806TIL</guid>
            <pubDate>Wed, 05 Aug 2020 15:49:14 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p><strong>스코프와 클로저의 개념에 대해서 배웠다.</strong> 반복문 코플릿 문제를 풀 때, 왜 for문 바깥에서 변수를 정의하고 들어가야하는지 궁금했었는데 이 부분을 잘 공부하면 궁금증을 풀 수 있을 것 같다. 특히 클로저 부분이 어려웠다. 소크라티브 문제들을 내일 솔루션 전에 살펴봐야겠다. 솔루션 시간에 이해할 수 있으면 좋겠다.</p>
</li>
<li><p><strong>javascirpt koans</strong>를 일부 풀고 제출하였다. git으로 커밋하는 과정에 대해 조금은 익숙해진 것 같다. koans 문제들은 코플릿 문제보다는 수월한 편이었지만, 문제를 풀기 위해서는 문제에서 필요로 하는 내용들을 검색하고 숙지해야 풀 수 있는 문제들이었다. 유어클래스 강의들과 코플릿 문제들을 풀면서 배운 것들을 더 다듬을 수 있는 기회였다. 답은 제출했지만 그 과정이 이해되지 않는 것들도 있었다. 시간이 허락한다면 Advanced koans도 다 풀고 싶다.</p>
</li>
<li><p><em>오늘은 <strong>코플릿 복습</strong>은 거의 하지 못했다. 위의 것들을 하는 데만도 시간을 많이 써버렸기 때문이다. 어제와 오늘은 pair가 없는 날이었는데, 확실히 동기 분이랑 같이 공부하면 집중이 더 잘되는 면이 있다. 문제는 내가 보폭이 작아서 허겁지겁 따라간다는 점. 모각코, 헬프데스크 잘 이용하기!</em></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[200804_TIL]]></title>
            <link>https://velog.io/@ys_sung/200805</link>
            <guid>https://velog.io/@ys_sung/200805</guid>
            <pubDate>Tue, 04 Aug 2020 15:21:27 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p><strong>유닉스 명령어에 대해서 배웠다.</strong> 현재 디렉토리에 있는 파일과 디렉토리의 리스트를 찾는 명령어(ls), 빈 파일(touch)과 디렉토리 생성하는 명령어(mkdir) 등에 대해서 배웠다. 우분투를 설치하면서 몇 개는 자연스럽게 알게 되긴 했지만 그래도 모르는 것들이 있었다. 터미널을 사용하는 것에 익숙해지도록 하자</p>
</li>
<li><p><strong>git 사용법에 대해서도 배웠다.</strong> 리모트 레파지토리에서 포크(Fork)와 클론(Clone)을 통해서 내 컴퓨터의 디렉토리에 다운로드하는 법을 배웠다. 그리고 반대로 git status -&gt; git add -&gt; git commit -m -&gt; git push라는 명령어로 스테이지 에이리어에 add하고 로컬 레파지토리에 commit하고, 마지막으로 리모트 레파지토리에 push해서 다른 사람들도 코드를 볼 수 있도록 업로드하는 법을 배웠다. </p>
</li>
<li><p><strong>코플릿 문제를 복습하였다.</strong> 주로 반복문 문제를 공부했는데, 아주 어려웠다. 특히 숫자를 인자로 받아서 그 숫자가 소수인지 아닌지를 불리언으로 리턴하는 문제가 특히 어려웠다.
그래도 알게 된 것.</p>
</li>
</ul>
<ol>
<li><p>이중 for문을 디버깅해보면서 어떤 순서로 반복하는지 알았다. (첫번째 반복문 1 - 두번째 반복문 12345 - 첫번째 반복문 2 - 두번째반복문 12345 ...) </p>
</li>
<li><p>반복문의 초기화, 조건문, 증감문이 어떤 순서로 실행되는지 알게되었다. for문에 진입할 때는 초기화를 실행하고, 반복하는 과정에서는 조건문과 증감문을 번갈아가며 확인한다. 초기화-&gt;조건문-&gt;반복-&gt;증감문-&gt;조건문, 그리고 이중for문의 경우에는 더 상위의 for문과 번갈아 코드가 실행되면서 초기화부분이 반복적으로 실행된다는 것도 알았다.</p>
</li>
</ol>
<ul>
<li><p><strong>Javascript koans</strong> 코드스테이츠의 레파지토리에서 클론하여 내 디렉토리에 내려받고 문제를 풀어서 push까지 하는 과정까지가 과제였다. 그동안 배운 자바스크립트의 문법들을 점검함과 동시에, 실제 워크플로우가 어떻게 흘러가는지 이해하는 데 목적이 있는 것 같은 과제 같다고 생각했다. 오늘은 복습에 시간을 많이 써서 많이 하지 못했다. 내일 많이 따라잡아야겠다.</p>
</li>
<li><p><em>다른 분들에 비해 나의 진도가 느린 것 같아 걱정이다.</em></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[<IM 후기 공유회>메모]]></title>
            <link>https://velog.io/@ys_sung/IM-%ED%9B%84%EA%B8%B0-%EA%B3%B5%EC%9C%A0%ED%9A%8C%EB%A9%94%EB%AA%A8</link>
            <guid>https://velog.io/@ys_sung/IM-%ED%9B%84%EA%B8%B0-%EA%B3%B5%EC%9C%A0%ED%9A%8C%EB%A9%94%EB%AA%A8</guid>
            <pubDate>Thu, 30 Jul 2020 13:14:01 GMT</pubDate>
            <description><![CDATA[<p>-코드스테이츠 &#39;IM 후기 공유회&#39;를 시청하고 메모를 해보았다. 일정이 있어서 앞부분과 중간에 시청을 하지 못했다. <em>(중간에 프로젝트 관리에 관한 부분을 놓쳐서 아쉽다.)</em> 최대한 한 부분의 메모를 정리하였다. 발표하신 분들 모두 멋진 분들 같았고 나도 5달 뒤에 저런 모습을 많이 배웠으면 좋겠다. <strong><em>제발!</em></strong></p>
<hr>
<h2 id="초보에게-조언">초보에게 조언</h2>
<ul>
<li><p>&lt;바로바로 질문하기&gt; 
나중에 질문하면 질문의 맥락을 까먹기도 하기 때문이다. 질문을 함으로써 무엇을 모르는지 아는 경우도 많으니 일단 일단 질문하기</p>
</li>
<li><p>&lt;Urclass에 너무 의존하지 않기&gt;
잘하는 사람의 비결은 다양한 튜토리얼을 참고하는 것이다. Urclass에 있는 것을 다 이해하지 못했다고 해서 몇 번이고 반복해서 보지 말 것.</p>
</li>
</ul>
<hr>
<h2 id="기록은-어떻게">기록은 어떻게?</h2>
<ul>
<li><p>&lt; TIL &gt;
블로깅 쓰는 고정시간 정하기<em>(내 경우엔 아침이 좋겠다)</em>, 작성시간 끝나면 마무리하고 올린다. (Maximum 1hr), 완벽할 필요x, TIL 작성의 목적은 성실성을 증명하기 위한 것이다.</p>
</li>
<li><p>&lt; DeVlog &gt; 
코드스테이츠 프로젝트 2개, 스프린트 단위로 진행사항 기록//고민을 해결한 방법 등을 기록하면 좋다. 프로젝트에 모든 에너지를 쏟아붓는 것보다 블로깅할 에너지를 남겨두는 편이 좋다.</p>
</li>
<li><p>&lt;깃헙&gt;
1일 1커밋을 하려고 최대한 노력(블로깅과 마찬가지로 성실함을 내보이기 좋다) 그렇다고 너무 부담감 갖지 않고 꾸준히 하다보면 좋은 결과. 평일은 토이/ 주말은 스프린트 진행 중 어렵거나 다시 짚을 부분을 토이프로젝트 or 튜토리얼.</p>
</li>
<li><p>여러 레퍼런스와 강의 적극 이용해서 전공지식 습득</p>
</li>
</ul>
<hr>
<h2 id="프로젝트">프로젝트</h2>
<ul>
<li>&lt;프로젝트 진행할 때 놓치기 쉽지만 중요한 팁&gt;
프로젝트 진행과정 : (1)아이디어 모집/팀결성 <strong><em>(2)기획(SR)</em></strong> (3)개발 (4)발표</li>
<li>-&gt;기획이 가장 중요</li>
</ul>
<p>[이 부분을 놓쳐서 메모를 못했다. 녹화영상 올라오면 채울 것] </p>
<hr>
<h2 id="지치지-않고-완주하기">지치지 않고 완주하기</h2>
<ul>
<li>목차</li>
</ul>
<ol>
<li>코스루틴  2.취업준비루틴</li>
</ol>
<p>&lt;1 . 코스루틴&gt;</p>
<ul>
<li><p>나만의 루틴을 짜자 : <strong><em>나만의 페이스</em></strong> 유지하는 것이 중요</p>
</li>
<li><p>스스로에 대해 분석해보기 : 집중과 휴식? or 길고 여유있게? // 아침형? or 저녁형? // 스트레스 해소법은 어떻게<em>(난 운동!)</em> 수면시간은 6~7시간은 유지할 수 있도록.(주말에 조금 더 보충)</p>
</li>
<li><p>해야하는 것<em>(코스,자습,기록하기,외부튜툐)</em> + 하고싶은 것<em>(운동, 독서 : 아침 루틴에 포함시키고 싶어)</em> ---&gt; 루틴!</p>
</li>
<li><p>주중의 루틴 예시를 참고해서 대강의 나의 루틴.
(아침 6시 기상 : 운동, 블로깅, 미리 공부할 거 조금, 독서)---(코스 일정 소화)---(복습 : 과제, 기타 추가 공부할 것) ---(11시 취침)</p>
</li>
<li><p>주말 루틴.
(기상시간 9시) -- (공부 3시간 이상)</p>
</li>
</ul>
<p>&lt;2. 취업준비루틴&gt;</p>
<ul>
<li><p>힘든 20주 과정을 수료하고 나면 놀고싶은 유혹이 반드시 찾아온다. </p>
</li>
<li><p>--&gt; 그러나 수료 후 루틴이 취업을 좌우한다.</p>
</li>
<li><p>시키지 않아도 <strong><em>스스로 지킬 수 있을</em></strong> 정도의 스케쥴.</p>
</li>
<li><p>역시 마찬가지로 해야하는 것(공부, 개인프로젝트, 취업준비) + 하고싶은 것(운동, 독서)을 적절하게 조합해서 루틴을 구성할 것.</p>
</li>
</ul>
<p>-취업준비 + 부족한 것 보완의 예시 : 알고리즘, 어려웠던 스프린트 복습, 개인 프로젝트...</p>
<ul>
<li>자소서나 컴퍼니서치는 조금씩 자주 하기.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[200729_TIL]]></title>
            <link>https://velog.io/@ys_sung/200729TIL</link>
            <guid>https://velog.io/@ys_sung/200729TIL</guid>
            <pubDate>Tue, 28 Jul 2020 16:44:43 GMT</pubDate>
            <description><![CDATA[<h2 id="오늘-한-일">오늘 한 일</h2>
<ul>
<li><p>코플릿에서 pair programming으로 <strong><em>조건문</em></strong> 문제풀이를 했다. 함수 속에 계산기 만들기, 특정 달(month)을 입력하면 그 달이 며칠인지 출력하는 조건문, 둘 중 하나는 짝수이고 두 수 모두 어떤 숫자보다 작다라는 두 조건을 모두 만족하는지 검사하는 조건문 등이 기억에 남고 어려웠다. 진도를 따라가기 위해서는 추가학습이 많이 필요하다.</p>
</li>
<li><p>의사코드를 활용해서 코딩하는 법을 연습해보았다. 더 확실히 익혀야겠다.</p>
</li>
<li><p><em>페어 프로그래밍은 어제보다 페어 분이 조금은 편안햬져서 더 좋았다. 페어 분이 친절한 분이라 다행이라고 생각했다. 네비게이터와 드라이버로 역할을 나누어서 코딩하는 방법은 아직은 조금 어색하다. 네비게이터인데 끼어들고, 드라이버인데 방향을 지시하는 등의 실수가 있었다.</em></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[200727_TIL]]></title>
            <link>https://velog.io/@ys_sung/200727TIL</link>
            <guid>https://velog.io/@ys_sung/200727TIL</guid>
            <pubDate>Mon, 27 Jul 2020 23:59:34 GMT</pubDate>
            <description><![CDATA[<p>코드스테이츠 20주 과정의 첫날이다.
스스로 잘 할 수 있을까라는 두려움도 들었지만, 나처럼 개발자로 취직하기 위해 모여든 다른 분들의 얼굴들을 보며 잘 하고 싶다고 되새겼다.</p>
<p>Pair Programming은 초면인 분과 같이 문제를 푸는 게 조금 어색했지만, 또 금방 익숙해지기도 했다. 이렇게 어색함과 익숙함을 오가면서 커뮤니케이션 능력을 기르는 데 집중하자.</p>
<p>그와 별개로 코플릿 문제들 중 몇개는 잘 풀리지 않아서 한참을 붙잡고 있었다. 그 중의 두 문제는 다음날 풀어보니 생각보다 간단한 문제라서 조금 부끄러웠다. 과정을 따라가기 위해선 많은 시간 투자가 필요하다.</p>
<h1 id="today-i-learned">Today I learned</h1>
<h3 id="좋은-질문을-하는-법">&lt;좋은 질문을 하는 법&gt;</h3>
<ul>
<li>좋은 질문을 한다는 것이란 물어보는 것을 <strong><em>글로</em></strong> 쓸 줄 안다는 것.</li>
</ul>
<h4 id="검색이-먼저다">검색이 먼저다</h4>
<ul>
<li>이해가 안되더라도 에러메시지 읽어보는 습관.</li>
<li>여러가지 방법으로 에러를 구글링 해보기, 무엇을 찾아봤는지 기록.</li>
<li>검색은 내 질문을 개선하기 위해 하는 것.</li>
<li>더 나은 질문, Keyword를 얻기 위해서.</li>
</ul>
<h4 id="검색으로-해결이-안되면-반드시-질문">검색으로 해결이 안되면 반드시 질문</h4>
<ul>
<li>상황설명은 어렵고 질문자는 보통 무엇을 모르는지도 모른다.</li>
<li>질문은 그것을 연습하는 것.</li>
<li>빠르게 성장하기 위해서는 질문은 선택이 아니라 필수.</li>
<li>그러나 질문은 정성들여서 해야 한다. 질문하는데 개선이 되지 않는다면? 뭔가 잘못되고 있다.</li>
</ul>
<h4 id="좋은-질문을-하기-위한-팁들">좋은 질문을 하기 위한 팁들</h4>
<ul>
<li>좋은 질문은 제목이 좋아야 한다. (내용 먼저 쓰고 그 내용을 잘 요약하는 방식도 좋다. 짧고 간단한 제목보다 상세하게 정보를 담고 있는 서술형이 좋다.)</li>
<li>바쁜 동료에게 물어본다고 생각.</li>
<li>코드를 붙여넣기 전에 상황을 설명하기. 시도한 흔적과 시도해서 얻은 오답들을 함께 설명하기.</li>
</ul>
<h4 id="답변으로-문제를-해결-했다면">답변으로 문제를 해결 했다면</h4>
<ul>
<li>그 답변으로 어떻게 문제를 해결했는지 상세히 설명하기.(내 질문으로 도움받을 사람들을 위해)</li>
<li>답변자에게 진심으로 감사하기.</li>
</ul>
<h3 id="변수와-자료형">&lt;변수와 자료형&gt;</h3>
<blockquote>
<p><strong><em>변수(variable)</em></strong>는 이름이 붙은 값을 의미한다. 여기에서 값은 계속 변경할 수 있다. 먼저 변수를 선언하고 그 변수에 임의의 값을 할당할 수 있다. 값은 여려가지 형식이 있는데 이것을 <strong><em>자료형(type)</em></strong>이라고 한다. type에는 문자열, 숫자, Boolean 등이 있다.</p>
</blockquote>
<p>변수의 선언과 할당은 다음과 같이 한다.</p>
<pre><code class="language-javascript">let fruit;
fruit = apple;</code></pre>
]]></description>
        </item>
    </channel>
</rss>