<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>smurf_.log</title>
        <link>https://velog.io/</link>
        <description>It's the smurf smurf smurf! </description>
        <lastBuildDate>Tue, 19 Sep 2023 07:54:22 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>smurf_.log</title>
            <url>https://velog.velcdn.com/images/smurf_/profile/581031f1-1545-4fd5-9ce2-fac21000114a/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. smurf_.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/smurf_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[0919_TIL.1]]></title>
            <link>https://velog.io/@smurf_/0919TIL.1</link>
            <guid>https://velog.io/@smurf_/0919TIL.1</guid>
            <pubDate>Tue, 19 Sep 2023 07:54:22 GMT</pubDate>
            <description><![CDATA[<p><em><a href="https://fe-developers.kakaoent.com/2022/221013-tailwind-and-design-system/">https://fe-developers.kakaoent.com/2022/221013-tailwind-and-design-system/</a></em>
참고하였습니다</p>
<h2 id="cssinjs-의-재발견">CSSINJS 의 재발견</h2>
<ul>
<li>어찌됐던 CSS의 탈을 쓴 JS 이기때문에 로딩이 있을수있다 (버그성깜빡임)</li>
<li>styled 칸이 길어질수록 코드 칸이 길어져서 오히려 가독성을 해칠수 있음 </li>
<li>비슷한 페이지의 공통 디자인을 뭉치기가 어려울 수 있음 =&gt;<br>themeProvider 를 사용할경우 거의 모든 컴포넌트의 보일러플레이트가 될 수 있음. </li>
</ul>
<h2 id="tailwind의-재발견">TAILWIND의 재발견</h2>
<ul>
<li>IntelliSense 이 된다. 생각해보니 타입스크립트 자동완성으로 굉장히 편리함을 느꼈었으니...</li>
<li>빠르고쉬운 반응형 / 레이아웃 잡기  디자인 통일성</li>
</ul>
<h2 id="그치만-tailwind의-디자인이">그치만 tailwind의 디자인이...</h2>
<p>프론트입장에서 테일윈드의 디자인은 너무 평범하고 성격상 뜯어고치고 내것으로 만들고싶기 때문에 알아본결과 
<strong>twinmacro</strong> 라이브러리를 이용해서 cssinjs(나같은경우 스타일드컴포넌츠)와 함께 이용하면 어느정도 고민이 해결된다.
컴포넌트별 UI 는 CSSINJS 로잡고 pr전체적인 서비스의 틀(레이아웃,컬러가이드)은 테일윈드로 빠르게 잡아 작업기간을 줄일수 있을것이다. </p>
<p>또 동적으로 컨트롤해야하는 부분은 twinmacro 로 처리해서 cssinjs 의 큰 기능인 props 로 받아오는 동적 스타일도 커버가될수있다..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[0917.TIL1]]></title>
            <link>https://velog.io/@smurf_/0917.TIL1</link>
            <guid>https://velog.io/@smurf_/0917.TIL1</guid>
            <pubDate>Sun, 17 Sep 2023 15:47:28 GMT</pubDate>
            <description><![CDATA[<h2 id="lazy-initialization">Lazy Initialization</h2>
<pre><code class="language-js">export const useLocalStorage = (key, initialValue) =&gt; {
  const [value, setValue] = useState(() =&gt; {
    return getSavedValue(key, initialValue);
  });
  return [value, setValue];
};
</code></pre>
<p>이러한 예제에서  useState값 안에 익명함수가 있다.
<code>const [value, setValue] = useState(getSavedValue(key, initialValue));</code>
와
<code>const [value, setValue] = useState(() =&gt; {
    return getSavedValue(key, initialValue);
  });</code>
  의 차이는 무엇일까 ?</p>
<h2 id="오직-한번">오직 한번</h2>
<ul>
<li>useState안에 익명함수를 넣으면 이 state가 만들어 질 때만 실행된다 . 그이후 재 렌더링시 무시한다.</li>
</ul>
<h2 id="만약-사용을-안하면">만약 사용을 안하면?</h2>
<p>  그냥 useState안에 <code>getSavedValue()</code>만 넣으면</p>
<ol>
<li>state가 렌더링될때 getSavedValue()를 실행한다.</li>
<li>그이후로 setState로 값이 변경되면 전체 함수(컴포넌트)가 다시 실행되며 state값을 업데이트한다. -&gt; 리렌더링을 발생</li>
<li>리렌더링이되면 state는 다시 getSavedValue() 를 실행한다.(불필요한 계산)</li>
</ol>
<h2 id="그렇다면-언제사용할까-">그렇다면 언제사용할까 ?</h2>
<ul>
<li>보통 map,filter,find 배열을 조작하는것에 사용 (느림)</li>
<li>localStorage 접근시 사용 ( 역시느림)</li>
<li>new Date()  (느림)</li>
<li>느린 함수를 사용할때 주로 사용한다.</li>
</ul>
<h2 id="내경우">내경우</h2>
<ul>
<li>내 경우엔, 내가만든 getSavedValue안에는 JSON.parse(느림)
과 localStorage접근이 둘다 있어서, <strong>최적화</strong>의 이유로 state에서 익명함수를 사용한다. </li>
<li>기억하고 리팩토링 / 최적화시에 적용하는 버릇을 들이자 .</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[0916 TIL.1]]></title>
            <link>https://velog.io/@smurf_/0916-TIL.1</link>
            <guid>https://velog.io/@smurf_/0916-TIL.1</guid>
            <pubDate>Sat, 16 Sep 2023 11:00:23 GMT</pubDate>
            <description><![CDATA[<p><del>꺾인다..</del></p>
<h2 id="custom-hooks">custom Hooks</h2>
<ul>
<li>polymorphic 하게  ? : 을 이용하여 default값을 정해주기</li>
<li>useEffect안에 들어간다 하면 useCallback 이용하여 렌더링 막아주기</li>
<li>컴포넌트에 memoization 이 싫다면, 의존성을 최소화하기 </li>
</ul>
<h2 id="custom-hooks-return-array--object-">custom hooks return Array ? Object ?</h2>
<ul>
<li>관습상 return 이 2개일경우 useState같은 모양으로 배열</li>
<li>그이상은 3개로 </li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[0912 TIL.]]></title>
            <link>https://velog.io/@smurf_/0912-TIL</link>
            <guid>https://velog.io/@smurf_/0912-TIL</guid>
            <pubDate>Tue, 12 Sep 2023 11:45:52 GMT</pubDate>
            <description><![CDATA[<p>리액트 리팩토링 과정에서 커스텀훅을 신경 쓰지 못했다. </p>
<p>그래서 커스텀훅 만들 생각을 보강하고자 여러 예시 제작을 해보려한다. </p>
<h3 id="커스텀훅-신경써야할것">커스텀훅 신경써야할것</h3>
<ul>
<li><p>재사용가능한 함수에 상태를 설정하는 로직을 외부에서 설정하고 관리 할 수 있게 한다. =&gt; 함수를 호출 할 때 마다 매번 초기화하거나 재설정 하지 않고 그때 그때 사용할 수있다.</p>
</li>
<li><p><em>=&gt; 로직을 외부에서 설정하고 관리할 수 있는 함수라면 커스텀훅으로 변경한다 .*</em></p>
</li>
<li><p>boolean을 컨트롤하는 useState는 커스텀훅으로 만드는것이 좋다.</p>
</li>
<li><p>정규함수와는 다르게, 커스텀 훅은 다른 커스텀 훅을 포함한 다른 리액트 훅을 사용 할 수 있다 .useState, useReducer useEffect 등 </p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[0911 TIL1.]]></title>
            <link>https://velog.io/@smurf_/0911-TIL1</link>
            <guid>https://velog.io/@smurf_/0911-TIL1</guid>
            <pubDate>Mon, 11 Sep 2023 07:39:48 GMT</pubDate>
            <description><![CDATA[<h2 id="onchange의-렌더링-최적화를-위해서">OnChange의 렌더링 최적화를 위해서</h2>
<p>onChange안에 있는 setState에 prev을 이용하여 렌더링 최적화를 해준다</p>
<pre><code class="language-ts">
onChange={(e)=&gt;{
  setState((prev)=&gt;{
  if(prev !== e.target.value) {
    return  e.target.value;
              }
          })
    }</code></pre>
<h2 id="remove-문제">Remove 문제</h2>
<ul>
<li>원인 : 삭제버튼을 누르면 전부다 삭제되는 현상<pre><code>//문제 removeMemo 
</code></pre></li>
</ul>
<p>removeMemo(id){
set(state=&gt;({
memoList:[state.memoList.filter(e=&gt;e.id!==id)],
})
}</p>
<pre><code>원하던 기술은 버튼누르면 해당 id와 맞는 컴포넌트만 언마운트되어야하는데 그러지않았다.


생각해보니  removeMemo 함수 안에있는 memoList 키에 [] 배열을 넣으면 배열이 중첩되는현상이 생길거같았다.
state.memoList 자체가 배열인데 기존배열위에 배열을 한번감싸니 삭제버튼을 누르는순간 배열이 바뀌어버려 전부다 없어지는현상(삭제되는거처럼보임) 

* 해결 </code></pre><p>//문제 removeMemo </p>
<p>removeMemo(id){
set(state=&gt;({
memoList:state.memoList.filter(e=&gt;e.id!==id),
})
}</p>
<pre><code>addMemo 처럼 작성하다가 생긴 오류인것 같다. </code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[0910.TIL2]]></title>
            <link>https://velog.io/@smurf_/0910.TIL2</link>
            <guid>https://velog.io/@smurf_/0910.TIL2</guid>
            <pubDate>Sun, 10 Sep 2023 12:49:51 GMT</pubDate>
            <description><![CDATA[<h2 id="css-function">CSS FUNCTION</h2>
<ul>
<li>var() : 변수화하여 전역사용</li>
<li>calc() : 계산</li>
<li>min() : 내가 지정한 값중에 제일 최소</li>
<li>max() : 제일 최대</li>
<li>clamp() : 적용</li>
<li>env() : 노치있는 스마트폰 노치영역 작업할떄 </li>
</ul>
<h4 id="path-interllisense-사용시">Path interllisense 사용시</h4>
<pre><code>/* vscode setting.json에 추가 설정 */

&quot;typescript.suggest.paths&quot;: false,
&quot;javascript.suggest.paths&quot;: false</code></pre><p>하기</p>
<ul>
<li>TS환경에서 사용 하려면<pre><code>//tsconfig
//ts.config.compilerOptions.baseUrl
{
  &quot;baseUrl&quot;: &quot;src&quot;,
}
</code></pre></li>
</ul>
<p>```</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[0910 TIL1. zustand ]]></title>
            <link>https://velog.io/@smurf_/0910-TIL1.-zustand</link>
            <guid>https://velog.io/@smurf_/0910-TIL1.-zustand</guid>
            <pubDate>Sun, 10 Sep 2023 12:46:37 GMT</pubDate>
            <description><![CDATA[<h2 id="zustand-한입-하기">zustand 한입 하기</h2>
<ul>
<li>기존에 사용하던 RTK 이 너무 지저분하고 복잡하기때문에 다른 상태관리 라이브러리를 찾던중 여러사람들이 추천한 zustand를 사용해보자</li>
</ul>
<h3 id="상태관리란">상태관리란,</h3>
<p>React는 단방향 바인딩이기 때문에 다른페이지 다른컴포넌트와의 상태를 공유하기 위해선 <strong>상위컴포넌트로 끌어올린후 다시 다른 컴포넌트로 보내줘야한다</strong> ( 매우더러움 )
Props Drilling 현상이 생김. 
상태관리를 사용하지 않았던 나는 두번째 팀프로젝트에서 프롭스 드릴링을 경험했고.. 무너지는 상태를(무너지는 내멘탈) 보고 
상태관리 라이브러리의 중요성을 깨달았다.</p>
<p>기존 사용하던 Redux ToolKit와 같이 Zustand는</p>
<p><strong>FLUX</strong>패턴을 기반(중앙 스토어 활용해서 여러 컴포넌트에 뿌려줌 / 액션을통해 데이터를 조작함 ) 으로 되어있다.</p>
<h3 id="설치">설치</h3>
<p><code>npm i zustand</code>
끝</p>
<h3 id="사용">사용</h3>
<p><code>import {create} from &quot;zustand&quot;;</code>
끝 </p>
<h3 id="store-저장">store 저장</h3>
<pre><code>const useStore = create(set =&gt;({
초기값 :0,
함수들() {set(state =&gt;({초기값: state.초기값 +}))}
})</code></pre><h3 id="store-활용">store 활용</h3>
<ul>
<li>리액트 훅처럼 사용하면 된다. (매우편함)<pre><code class="language-ts">function App() {
const {초기값,함수들} = useStore()
return (
&lt;div className=&quot;App&quot;&gt;
&lt;p&gt;{초기값}&lt;/p&gt;
&lt;button onclick={()=&gt;함수들()}&gt;&lt;/button&gt;
&lt;/div&gt;
)
}</code></pre>
</li>
</ul>
<h3 id="zustand는-response-도-받아온다">zustand는 response 도 받아온다.</h3>
<pre><code>``` useStore = create(set=&gt;({
async getData() {
const res = await fetch(https);
const data = res.json();
}
})</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[0909 TIL.1]]></title>
            <link>https://velog.io/@smurf_/0909-TIL.1</link>
            <guid>https://velog.io/@smurf_/0909-TIL.1</guid>
            <pubDate>Sat, 09 Sep 2023 21:00:41 GMT</pubDate>
            <description><![CDATA[<p>오늘배운것</p>
<ul>
<li><p>삼항연산자는 가독성을 해치니 고려하여 사용할것</p>
</li>
<li><p>boolean 형태의 state관리는 재사용성이 높으므로 커스텀훅으로 작성할것.</p>
</li>
<li><p>props에 들어가는 변수를 옵셔널로 사용하는건 자제할 것.</p>
</li>
<li><p>React.FC 는 사용안해두됨. (디자인패턴에따라다름)</p>
</li>
<li><p>interface 말고 type 을 주로사용해보자 </p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[react project 초기설정하기 ]]></title>
            <link>https://velog.io/@smurf_/react-project-%EC%B4%88%EA%B8%B0%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@smurf_/react-project-%EC%B4%88%EA%B8%B0%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 09 Sep 2023 18:51:06 GMT</pubDate>
            <description><![CDATA[<p>CRA로 프로젝트 환경을 구축하고 eslint 와 prettier ts 를 곁들일때 설정법을 기록했다.</p>
<h3 id="설치-리스트">설치 리스트</h3>
<ul>
<li><p><code>npx create-react-app ./ --template typescript</code></p>
</li>
<li><p><code>npm i react-router-dom</code></p>
</li>
</ul>
<p><strong>SASS/Styled-components</strong></p>
<ul>
<li><code>npm i sass --save</code></li>
<li><code>npm i styled-components</code></li>
</ul>
<p><strong>Prettier</strong></p>
<ul>
<li><code>npm i prettier -D</code></li>
</ul>
<p><strong>ESLINT</strong> eslint는 CRA 에 내장되어있기에 prettier 플러그인만 설치</p>
<ul>
<li><code>npm i eslint-config-prettier eslint-plugin-prettier</code></li>
<li><code>npm i -D eslint-plugin-react eslint-plugin-react-hooks</code></li>
<li>초기설정을 진행 해준다.</li>
<li><code>npx eslint --init</code></li>
</ul>
<h3 id="eslintrc">.eslintrc</h3>
<p>최상단에 .eslintrc를 만들고 작성한다</p>
<pre><code class="language-js">{
    &quot;extends&quot;: [&quot;react-app&quot;, &quot;plugin:prettier/recommended&quot;],
    &quot;rules&quot;: {
        &quot;no-var&quot;: &quot;warn&quot;, // var 금지
        &quot;no-multiple-empty-lines&quot;: &quot;warn&quot;, // 여러 줄 공백 금지
        &quot;no-nested-ternary&quot;: &quot;warn&quot;, // 중첩 삼항 연산자 금지
        &quot;no-console&quot;: &quot;warn&quot;, // console.log() 금지
        &quot;eqeqeq&quot;: &quot;warn&quot;, // 일치 연산자 사용 필수
        &quot;dot-notation&quot;: &quot;warn&quot;, // 가능하다면 dot notation 사용
        &quot;no-unused-vars&quot;: &quot;warn&quot;, // 사용하지 않는 변수 금지
        &quot;react/destructuring-assignment&quot;: &quot;warn&quot;, // state, prop 등에 구조분해 할당 적용
        &quot;react/jsx-pascal-case&quot;: &quot;warn&quot;, // 컴포넌트 이름은 PascalCase로
        &quot;react/no-direct-mutation-state&quot;: &quot;warn&quot;, // state 직접 수정 금지
        &quot;react/jsx-no-useless-fragment&quot;: &quot;warn&quot;, // 
        &quot;react/no-unused-state&quot;: &quot;warn&quot;, // 
        &quot;react/jsx-key&quot;: &quot;warn&quot;, // 반복문으로 생성하는 요소에 key 강제
        &quot;react/self-closing-comp&quot;: &quot;warn&quot;, // 셀프 클로징 태그 가능하면 적용
        &quot;react/jsx-curly-brace-presence&quot;: &quot;warn&quot;, // jsx 내 불필요한 중괄호 금지
        &quot;prettier/prettier&quot;: [
            &quot;error&quot;,
            {
                &quot;endOfLine&quot;: &quot;auto&quot;
            }
        ] // cr 에러 맥북과 병행하니 설정해둔다.
    }
}</code></pre>
<h3 id="prettierrc">.prettierrc</h3>
<p>역시 최상단에 생성, 작성</p>
<pre><code class="language-js">{
  &quot;printWidth&quot;: 80,
  &quot;tabWidth&quot;: 2,
  &quot;singleQuote&quot;: true,
  &quot;trailingComma&quot;: &quot;all&quot;,
  &quot;bracketSpacing&quot;: true,
  &quot;semi&quot;: true,
  &quot;useTabs&quot;: true,
  &quot;arrowParens&quot;: &quot;avoid&quot;,
  &quot;endOfLine&quot;: &quot;lf&quot;
}
</code></pre>
<h3 id="윈도우-vscode-settingsjson">윈도우 VSCode settings.json</h3>
<p>vscode 사용시 필요한 settings.json 을 추가해준다.</p>
<pre><code class="language-js">{
  &quot;editor.defaultFormatter&quot;: &quot;esbenp.prettier-vscode&quot;,
  &quot;editor.tabSize&quot;: 2,
  &quot;editor.formatOnSave&quot;: true,
  &quot;editor.codeActionsOnSave&quot;: {
    &quot;source.fixAll.eslint&quot;: true
  },
  &quot;javascript.format.enable&quot;: false,
  &quot;eslint.alwaysShowStatus&quot;: true,
  &quot;files.autoSave&quot;: &quot;onFocusChange&quot;
}
</code></pre>
<h3 id="gitignore-파일-설정">.gitignore 파일 설정</h3>
<p>기본적으로 웹스톰과 병행 사용하니,</p>
<pre><code class="language-node">/node_moudles
/.vscode
/.idea
.eslintcache</code></pre>
<p>작성한다</p>
<h2 id="typescript-관련-설정">typescript 관련 설정</h2>
<ul>
<li>이미 진행된 작업에서 타입스크립트를 추가시  라이브러리를 설치해준다<pre><code class="language-npm"></code></pre>
</li>
</ul>
<p>// <code>npm i @types/react @types/react-dom @types/node --save-dev</code> // </p>
<p>*tsconfig.json 설정도 해준다</p>
<pre><code class="language-js">{
  &quot;compilerOptions&quot;: {
    &quot;target&quot;: &quot;es6&quot;,
    &quot;lib&quot;: [
      &quot;dom&quot;,
      &quot;dom.iterable&quot;,
      &quot;esnext&quot;
    ],
    &quot;baseUrl&quot;: &quot;./src&quot;,
    &quot;allowJs&quot;: true,
    &quot;skipLibCheck&quot;: true,
    &quot;esModuleInterop&quot;: true,
    &quot;allowSyntheticDefaultImports&quot;: true,
    &quot;strict&quot;: true,
    &quot;forceConsistentCasingInFileNames&quot;: true,
    &quot;noFallthroughCasesInSwitch&quot;: true,
    &quot;module&quot;: &quot;esnext&quot;,
    &quot;moduleResolution&quot;: &quot;node&quot;,
    &quot;resolveJsonModule&quot;: true,
    &quot;isolatedModules&quot;: true,
    &quot;noEmit&quot;: true,
    &quot;jsx&quot;: &quot;react-jsx&quot;
  },
  &quot;include&quot;: [
    &quot;src&quot;
  ],
}
  // src 절대경로  설정 </code></pre>
<h3 id="ts-를-gh-pages-에-업로드하기">ts 를 gh pages 에 업로드하기</h3>
<p><code>npm i gh-pages --save</code></p>
<p><code>npm i @type/react --save</code></p>
<h3 id="html-parsed-error">html parsed error</h3>
<ul>
<li>html 에서 <strong>parsing error expression expected html</strong> 뜰경우,</li>
</ul>
<pre><code class="language-js">//eslint.rc
{
    &quot;plugins&quot;: [
        &quot;html&quot;
    ]
}</code></pre>
<p>추가한다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[위로 늘어나는 텍스트영역2]]></title>
            <link>https://velog.io/@smurf_/%EC%9C%84%EB%A1%9C-%EB%8A%98%EC%96%B4%EB%82%98%EB%8A%94-%ED%85%8D%EC%8A%A4%ED%8A%B8%EC%98%81%EC%97%AD2</link>
            <guid>https://velog.io/@smurf_/%EC%9C%84%EB%A1%9C-%EB%8A%98%EC%96%B4%EB%82%98%EB%8A%94-%ED%85%8D%EC%8A%A4%ED%8A%B8%EC%98%81%EC%97%AD2</guid>
            <pubDate>Fri, 09 Jun 2023 15:37:44 GMT</pubDate>
            <description><![CDATA[<h1 id="위로는-늘어나는데-왜-안줄어">위로는 늘어나는데 왜 안줄어</h1>
<ul>
<li>절망적이다 하루종일 작업을했지만 한번늘어난 scrollheight는 줄어들지않는다. 
정확히는 console.log로 찍어보니, textarea height 가 useRef로 지정되지 않으면scrollheight가 줄어들지않고. height값이 고정되어있으면 줄어든다.</li>
</ul>
<h2 id="height값이-고정되어있으면">height값이 고정되어있으면.</h2>
<p><img src="https://velog.velcdn.com/images/smurf_/post/69eb3a21-141f-4d00-ae3f-040b5eea39f6/image.png" alt=""></p>
<p>이런식으로 몇줄을 아무리적어도 커지지않는다..(당연)</p>
<h1 id="그럼-방법은">그럼 방법은..?</h1>
<ul>
<li><a href="https://www.npmjs.com/package/react-textarea-autosize">https://www.npmjs.com/package/react-textarea-autosize</a></li>
</ul>
<p><img src="https://velog.velcdn.com/images/smurf_/post/a99448ef-2fec-4202-b73f-7cb6301dd7b8/image.png" alt=""></p>
<p><em>이런게있는지몰랐네...</em></p>
<p>자동차를 만들자고 타이어부터 만들이유는 없지않는가... 라이브러리가 있더라...
아쉽지만 아쉽지않은 하루였다.. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[위로 늘어나는 텍스트영역]]></title>
            <link>https://velog.io/@smurf_/%EC%9C%84%EB%A1%9C-%EB%8A%98%EC%96%B4%EB%82%98%EB%8A%94-%ED%85%8D%EC%8A%A4%ED%8A%B8%EC%98%81%EC%97%AD</link>
            <guid>https://velog.io/@smurf_/%EC%9C%84%EB%A1%9C-%EB%8A%98%EC%96%B4%EB%82%98%EB%8A%94-%ED%85%8D%EC%8A%A4%ED%8A%B8%EC%98%81%EC%97%AD</guid>
            <pubDate>Thu, 08 Jun 2023 17:26:23 GMT</pubDate>
            <description><![CDATA[<h6 id="디버깅하면서-동시에-항상-문서화하는-습관을-들이자">디버깅하면서 동시에 항상 문서화하는 습관을 들이자.....</h6>
<h2 id="태그는-height-가-증가하면-주름마냥-밑으로-흐른다">태그는 height 가 증가하면 주름마냥 밑으로 흐른다.</h2>
<p>채팅방 관련 작업을 하다가 보여주는 화면은 100vh 로 영역에 딱 고정되어있으니.
채팅방 컴포넌트 작업을 하다가 텍스트 입력창의 영역을 value 길이에 맞춰 늘려보려 했다.</p>
<ol>
<li>자유로운 텍스트 입력을 위해 enter입력시 줄바꿈이 들어가야 한다.</li>
<li>줄바꿈이 들어가서 문장이 길어질때 태그의 높이도 그에 맞춰 가변적이어야 한다.</li>
<li>현 상황은 상위 태그가 100vh 로 고정되어있으니, 텍스트 입력창은 <strong>위로</strong> 증가 해야한다.</li>
</ol>
<hr>


<h2 id="1-줄바꿈이-가능한-input-">1. 줄바꿈이 가능한 input ?</h2>
<p>처음에는 input 태그에 <em>onKeyDown={handleEnter}</em> 함수로 enter입력시, 줄바꿈을 하려했다
<img src="https://velog.velcdn.com/images/smurf_/post/ae295953-4c9b-4eaf-9081-8a395f263c94/image.png" alt="">
<em>엥 ?</em>
이렇게 하니,메시지 전송후 말풍선에서는 줄바꿈이 적용되어 출력되지만,<br>정작 input 태그 입력창에서는 변화가 없었다. </p>
<ol>
<li>메시지전송 시 \n 가 입력되어 전달 해야함.</li>
<li>enter입력시 input 다음칸으로 내려가야함.</li>
</ol>
<h3 id="-해결">* 해결</h3>
<p>그래서 복잡하게 코드로 구현하기보단 <strong>textarea</strong>태그를 사용하기로 했다.
<code>border:none, outline:none,resize:none</code>으로 초기화 한뒤 
textarea 태그 내에서 enter 시 줄바꿈과,\n 저장이 제대로 되었다.</p>
<hr>

<h2 id="2-줄바꿈이-되었으니-입력창의-크기는-">2. 줄바꿈이 되었으니 입력창의 크기는 !?</h2>
<p>useRef/useEffect를 이용하여 enter입력시마다 height값이 커지게하면 되겠구나 ! 
<img src="https://velog.velcdn.com/images/smurf_/post/c17af6f1-087c-4cec-b334-c5b51a3fd06f/image.png" alt="">
<em>아?</em>
생각해보니 부모태그에 가변적으로 설정을 해둬야. 입력태그가 따라가겠다 생각하고</p>
<p><img src="https://velog.velcdn.com/images/smurf_/post/8c75ea37-193b-481b-849d-97b8dbec710f/image.png" alt="">
에 div 태그에 스타일을 주었다.
<img src="https://velog.velcdn.com/images/smurf_/post/c1c562cb-6c3f-4b03-a8d7-b2bac8eecef4/image.png" alt=""></p>
<p>오 늘어난다 늘어난ㄷ.?</p>
<hr>

<h2 id="3-입력창이-내려가요ㅜㅜ">3. 입력창이 내려가요....ㅜㅜ</h2>
<p>html 특성상 height값을 늘리면 아래로 내려갈테니 여기에 대해서 생각을 해봤다.</p>
<p>단순히, flex-direction column-reverse가 높이를 반대로 커지지 않게 할까 하고 설정해봤지만  되지 않았다...</p>
<p><img src="https://velog.velcdn.com/images/smurf_/post/d5432b7c-0db5-4bce-b2a3-00fcd3350f96/image.png" alt="">
<em>내려가지말라고...</em></p>
<h3 id="-해결-1">* 해결</h3>
<p>곰곰히 생각해보니 height가 커지면 영역이 밑으로 내려갈테니. 태그의 시작점을 위로 올리면 되지않나 ?
하고 margin-top을 음수로 처리하였다.</p>
<ul>
<li><p>useRef를 이용하여, textarea태그에 ref를 걸어두고,</p>
</li>
<li><p>useEffect 로 ref.current를 잡는다.</p>
</li>
<li><p>현재 textarea태그의 높이값을 scrollheight로 가져온다.
<img src="https://velog.velcdn.com/images/smurf_/post/83fc99b1-88b9-4969-97cd-a85dbb5fe962/image.png" alt=""></p>
</li>
<li><p>inputValue 값이 많아지면(줄바꿈이 많으면) 상태가 변화해야하니 useState도 사용한다.
(margin에 사용할state,height값에 사용할 state)</p>
</li>
<li><p>setState에 저장후, 스타일에 적용한다 !
<img src="https://velog.velcdn.com/images/smurf_/post/497b4d2d-afee-4817-9850-78de46454bf9/image.png" alt=""></p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/smurf_/post/310db2a8-c64f-405a-8c9f-4b39d51fa692/image.png" alt="">
<em>일단 원하는대로 작동을 하는데...</em></p>
<p>useEffect로 처음 setHeight를 잡다보니.처음 textarea태그가 -26px 위로 올라가있는다.
조절하여 내려준다.</p>
<p><img src="https://velog.velcdn.com/images/smurf_/post/b5de3846-32a3-4c96-abda-dfc362519d15/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/smurf_/post/828667ac-a4f5-4cc8-812f-193eac56372f/image.png" alt="">
<em>매우뿌듯</em> </p>
<h2 id="다음은-">다음은 ?</h2>
<ul>
<li>글자를 지우면 다시 줄어들게 하자.
<img src="https://velog.velcdn.com/images/smurf_/post/17042a45-df52-46fd-a046-49bf386618d1/image.png" alt=""></li>
</ul>
<p><em>좋았어..!</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[내가 몰라서 적는 REDUX 1.1]]></title>
            <link>https://velog.io/@smurf_/%EB%82%B4%EA%B0%80-%EB%AA%B0%EB%9D%BC%EC%84%9C-%EC%A0%81%EB%8A%94-REDUX-1.1</link>
            <guid>https://velog.io/@smurf_/%EB%82%B4%EA%B0%80-%EB%AA%B0%EB%9D%BC%EC%84%9C-%EC%A0%81%EB%8A%94-REDUX-1.1</guid>
            <pubDate>Sun, 21 May 2023 17:17:38 GMT</pubDate>
            <description><![CDATA[<h1 id="react-에서-redux-사용하기">React 에서 Redux 사용하기</h1>
<h2 id="store폴더">Store폴더</h2>
<ul>
<li>src/store 를 만들어 리덕스 관련 코드파일은 여기에 작성한다. </li>
<li>index.js를 만들어 리듀서 함수와 스토어를 만든다. <pre><code class="language-js">import { createStore } from &quot;redux&quot;;
const initialState = {
counter: 0,
};
</code></pre>
</li>
</ul>
<p>const counterReducer = (state = initialState, action) =&gt; {
  if (action.type === &quot;increment&quot;) {
    return { counter: state.counter + 1 };
  } else if (action.type === &quot;decrement&quot;) {
    return { counter: state.counter - 1 };
  } else {
    return state;
  }
};</p>
<p>const store = createStore(counterReducer);
//createStore는 더이상 안씀</p>
<p>//생성한 리듀서와 store를 컴포넌트와 연결하려면 export하면됨</p>
<p>export default store;</p>
<pre><code>## root/index.js
* export 까지 끝나면, 리액트 컴포넌트와 연결해주면된다.
* 리액트 저장소에 store를 제공하기위해 리액트의 최상단 index.js 에서 임포트한다.
```js
//index.js

import React from &quot;react&quot;;
import ReactDOM from &quot;react-dom/client&quot;;
import { Provider } from &quot;react-redux&quot;;
import &quot;./index.css&quot;;
import App from &quot;./App&quot;;
import store from &quot;./store&quot;;

const root = ReactDOM.createRoot(document.getElementById(&quot;root&quot;));
root.render(
  // Provider로 컴포넌트를 감싸주고 store={store}로 받아온다.
  &lt;Provider store={store}&gt;
    &lt;App /&gt;
  &lt;/Provider&gt;
);</code></pre><ul>
<li>이렇게 설정하면 작성한 리듀서함수를 모든 컴포넌트(App컴포넌트,하위컴포넌트)에 사용 가능하다.</li>
</ul>
<h2 id="useselector">useSelector</h2>
<ul>
<li><p>컴포넌트에서 Store 를 액세스 하려면
<code>import { useSelector } from &quot;react-redux&quot;;</code></p>
</li>
<li><p>를 작성하면된다.
(useStore 훅도 있는데 useSelector 가 더 사용하기 편함)</p>
</li>
<li><p>connect : 는 클래스컴포넌트에서 사용한다. </p>
</li>
<li><p><code>const counter = useSelector((state) =&gt; state.counter);</code></p>
</li>
<li><p>관리된 데이터를 콜백함수로 적고, 코드를 실행해서 컴포넌트에서 필요한 상태부분을 받는다.</p>
</li>
<li><p>useSelector 로 인해 store 에 데이터가 변경 될 때 마다  자동으로 업데이트되고 최신 값을 받게 된다.</p>
</li>
<li><p>값이 바뀌면 컴포넌트 함수가 리렌더링 됨.</p>
</li>
<li><p>컴포넌트를 unmount 하면 리덕스에서 자동으로 구독을 해지함.</p>
</li>
</ul>
<h3 id="잠깐">잠깐!</h3>
<ul>
<li>useSelector 는 자동으로 데이터가 변경을 감지해서 컴포넌트 함수를 리 렌더링 한다<pre><code class="language-js">const state = useSelector((state) =&gt; state);
const name = state.User.name;
const age = state.User.age;
const address = state.User.address;
</code></pre>
</li>
</ul>
<pre><code>이런식으로 작성하게 된다면.. name의 값이 바껴도 age와 address가 리렌더링 된다
최적화의 실패이기 때문에 
* 이런식으로 작성해줘야한다
```js
  const name = useSelector((state) =&gt; state.User.name);
  const age = useSelector((state) =&gt; state.User.age);
  const address = useSelector((state) =&gt; state.User.address);
// 리팩토링
  const { name, age, address } = useSelector((state) =&gt; state.User);</code></pre><p><strong>Store 에서 값을 저장하고 가져와서사용하는건 useSelector이다</strong> </p>
<h1 id="컴포넌트에서-action을-dispatch-하기-">컴포넌트에서 Action을 dispatch 하기 !</h1>
<ul>
<li>내부컴포넌트에서 데이터변경을 요청 하려면 useDispatch를 이용한다</li>
<li><code>import {useDispatch} from &#39;react-redux&#39;</code></li>
<li><code>const dispatch = useDispatch();</code></li>
<li>작성후 dispatch를 handle할 수 있는 함수를 작성한다 <pre><code class="language-js">const incrementHandler = () =&gt; {
 dispatch({ type: &quot;increment&quot; });
};
const decrementHandler = () =&gt; {
 dispatch({ type: &quot;decrement&quot; });
};</code></pre>
</li>
<li>그리고 버튼에 연결시키면 끝 !</li>
</ul>
<h2 id="정리">정리!</h2>
<ul>
<li>src/index.js 에 해당하는 리듀서 함수와 initialState 작성한다.</li>
<li>createStore(리듀서함수)를 export한다.</li>
<li>root index.js 에서 Provider를 import 한다.</li>
<li>리듀서를 원하는 컴포넌트에 가서 useSelector와 useDispatch 를 가져온다.</li>
<li>useSelector 로 state값을 가져오고 </li>
<li>dispatch(액션)을 함수로 작성후 onClick으로 연결한다. !</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[포스코X코딩온] 웹개발자 입문과정 10.1]]></title>
            <link>https://velog.io/@smurf_/%ED%8F%AC%EC%8A%A4%EC%BD%94X%EC%BD%94%EB%94%A9%EC%98%A8-%EC%9B%B9%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9E%85%EB%AC%B8%EA%B3%BC%EC%A0%95-10.1</link>
            <guid>https://velog.io/@smurf_/%ED%8F%AC%EC%8A%A4%EC%BD%94X%EC%BD%94%EB%94%A9%EC%98%A8-%EC%9B%B9%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9E%85%EB%AC%B8%EA%B3%BC%EC%A0%95-10.1</guid>
            <pubDate>Sat, 20 May 2023 08:26:40 GMT</pubDate>
            <description><![CDATA[<h1 id="팀-프로젝트">팀 프로젝트</h1>
<ul>
<li>수강하던 코딩온 수업에서 2치 풀스택 프로젝트를 진행하게 되었다.<blockquote>
<ul>
<li>프로젝트 소개와 주제 선정 배경 보다,프론트엔드를 다루면서 겪게된 트러블들, 그리고 그 트러블들을 해결한 트러블 슈팅에 중점을 두는 나만의 기록이다. <strong>Keep Problem Try 회고방법론을 통해서 적으려한다.</strong></li>
</ul>
</blockquote>
</li>
<li>이번 프로젝트를 통해서, 어떻게 작업을 해야할지 조금더 명확하게 깨닫게 되었다.</li>
</ul>
<h2 id="프로젝트와-주제">프로젝트와 주제</h2>
<blockquote>
<ul>
<li>조원들중 프론트/백엔드로 나뉘어 작업을 시작했다. 프로젝트는 다른 조원의 의견을 빠르게 수렴하여 작업을 시작했다.</li>
</ul>
</blockquote>
<p><em>. *</em>GPT를 이용한 멀티랭귀지 학습 기능 사이트**
*. 기능 사용에 중점을 두도록 대시보드 스타일의 웹페이지를 구현</p>
<h2 id="기억나는-진행과정">기억나는 ...진행과정...</h2>
<p>주제를 듣고...</p>
<ol>
<li>백엔드와 프론트 팀원들과의 머릿속 동기화(?) 를 위해 빠르게 와이어프레임을 진행</li>
<li>백엔드에선 백엔드대로 진행, 프론트팀은 바로 작업에 들어갔다.</li>
<li>첫번째 기획에선, 모바일사이트를 먼저 제작후 PC웹페이지를 만듬</li>
<li>레퍼런스 참고를 위해 자료조사 단계를 가졌다.</li>
<li>프론트팀원은 모바일 디자인 레퍼런스 조사 / 나는 pc화면 레퍼런스 조사</li>
<li>모바일 페이지 디자인 완성 (trouble 1)
7 . 코딩작업에 있어서 내가원하던 atomic design으로 폴더구조를 잡음</li>
<li>사용할 라이브러리를 조사하고, atoms 컴포넌트를 제작 trouble</li>
<li>styled-components 를 사용하기 위해 디자인토큰 작업 착수 troulble</li>
<li>회원가입 로그인 세팅 페이지 제작 css없이 레이아웃만 trouble</li>
<li>노반응형으로 전환</li>
<li>인터랙션 ui 를 위해 각 세부 컴포넌트에 Lottie 작업 (하루)</li>
<li>스켈레톤 UI 컴포넌트 생성,다크모드 생성,채팅리스트 컴포넌트</li>
<li>카카오 로그인 api 서버연결 시도</li>
<li>마지막날에 부족했던 회원가입과 로그인 CSS 작업 </li>
<li>서버배포과정</li>
</ol>
<h2 id="자기-피드백">자기 피드백</h2>
<h3 id="1-디자인작업에-너무-시간이-지체-되었다">1. 디자인작업에 너무 시간이 지체 되었다.</h3>
<blockquote>
<ul>
<li>뭔가 제대로 하고 싶은 마음에 피그마를 통해 디자인 과 레이아웃을 잡고.
디자인 토큰까지 활용 하여 CSS 에서 부담을 덜으려고 했으나
작업 시간에 이유로, 서둘러서 코딩작업에 들어간것. 중간중간 디자인상 변경사항으로인해 디자인토큰을 만들었으나 효율적으로 사용하지 못했다.</li>
</ul>
</blockquote>
<hr> 

<h4 id="k">K:</h4>
<p>피그마를 이용해서 한눈에 어떤식으로 작업해야할지. 눈으로 보면서 코딩을 작업 할 수 있었다. 확실히 이점이 있었다. 눈에 보이지 않고 머릿속에서만 구상했을 땐 중간중간 어떻게 만들까 라는 생각을 하면서 시간을 보냈는데... 피그마를 사용하니 눈에 보이는 결과물을 코딩하기만 하면되서<br>**   코딩과정에서 많이 시간단축이 있었다.... **
** 또 한가지 장점은 피그마의 핸드오프기능으로 인해<br>프론트 작업에서 CSS부분에서 시간단축이 있었다.**</p>
<h4 id="p">P:</h4>
<ul>
<li>피그마 내에서의 디자인작업속도가 너무 느려서. 전체적인 프론트엔드 작업진행에 뒤쳐졌다. 코딩과정에서 시간단축은 되었지만, 정작 프로젝트기간의 시간지체가 되었음. </li>
<li>섣부른 디자인 토큰 : 필요없었다. 결과론적으로 디자인이 바꼈기 때문에. 하루가 날라갔다.</li>
<li>프론트 팀원과의 디자인적 소통이 적었다. 소통이 적어서 디자인통일이 되지않았고 또  그 결과적으로 분업이 실패하였고 시간낭비 즉 비용이 생겼다.</li>
<li>프로젝트의 핵심기능을 먼저 제대로 디자인을 하고 그다음에 살을 붙이는게 맞았던거 같다. 정작 프로젝트 진행중 핵심 디자인인 채팅과 리스트에서 시간지체가 되었다.</li>
<li>일단 디자인하기전. 백엔드와 소통을 통해 웹페이지에서 필요한 오브젝트를 미리 설계 하고 시작했어야했다.
<strong>결과적으로 시간단축을 위해 사용하려던 피그마가 시간지체가 많이생김</strong><h4 id="t">T:</h4>
</li>
<li>디자인 통일감을 위해, 한명은 세부 컴포넌트 먼저 만들기 시작하거나, 최대한 빠르게 레퍼런스를 참고 해야 할 거 같다. </li>
<li>디자인을 시작하기전, 백엔드와 충분한 회의로 설계를 더 단단히 해야한다.</li>
<li><strong>중간에 노선을 바꾸지 말것</strong> 제일중요</li>
<li>디자인토큰은 나중에 CSS작업때 생각해봐도 될 것 같음.</li>
<li>피그마 활용능력을 기를것. 확실히 도움이 되는 부분이 있었기 때문.</li>
</ul>
<h3 id="2-atomic-design-에-시간이-너어무-할애됨">2. ATOMIC DESIGN 에 시간이 너어무 할애됨.</h3>
<blockquote>
<ul>
<li>프론트엔드 작업으로 보여줄 무언가는 클린코딩과 코드스플리팅 폴더구조라 생각해서.. 작업에 들어가기전 우리 팀은 ATOMIC DESIGN 을 이용하여 컴포넌트를 제작 하자고 했다.
ATOMIC DESIGN 자체를 이해하는데 시간이 걸렸고. 작은 아티클 하나하나 만들고 조합하는 과정에서 오래걸렸다</li>
</ul>
</blockquote>
<hr>

<h4 id="k-">K :</h4>
<p>아토믹디자인은 너무좋았다. 마치 레고와 같이 초반에 더디다는점은 아쉬웠지만, 나중에 페이지를 조합할 때 있어서 금방 페이지하나를 뚝딱뚝딱 할 수 있다. 추가로 컴포넌트를 제작할 때 어떻게 제작해야할지 감이 잡히기도하고 유지보수에 특히 좋았다. <strong>어느페이지의 어느버튼이 문제네 ! =&gt; atoms 에 버튼 수정.</strong></p>
<h4 id="p-">P :</h4>
<ol>
<li>ATOMIC DESIGN 을 온전히 이해하는데 걸리는 시간이 있었다.   </li>
<li>팀원간에 잦은 회의로 아토믹 디자인 설계를 빠르게 정립했어야했지만,
시간이 모자라 밀린 작업이 아토믹 디자인에 맞지 않았다.</li>
<li><strong>내실수</strong> : 시간이 모자르고 작업을 빠르게 하기위해 컴포넌트명을 대충 지었다. 그리고 또 나중에 수정을 했어야하지만. 그게아닌 다른 팀원도 내가 대충 지은 컴포넌트명을 따라시작하면서... 나중에 난리가 났다.<strong>(이게 무슨컴포넌트지...?)</strong></li>
<li>백엔드 팀원들도 이해못하는 폴더구조였다.</li>
<li><strong>아토믹디자인을 사용하려면 리덕스가 필수인거같다!!!!!</strong> 
프로퍼티 드릴링에 미쳐버렸었다. 더러워진 App.js 더러워진 프롭스...<h4 id="t-1">T:</h4>
</li>
<li>아토믹디자인 계속 써야한다. 모자란 리덕스도 공부해서 매꿔야한다.
사용해보니 진정한 리액트를 사용하는 느낌이었고 확실히 후에 유지보수에서 확실히 편리하였다.<del>(느린거는...)</del></li>
<li>컴포넌트명,변수명을 대충지으면 안된다. 진짜 안된다. <strong>당장에 다음주에 나도 못알아본다.</strong> 원래 하지 않는 행동이나 급해서 생긴 실수.</li>
<li>팀원들 회의에서 한번이라도 아토믹디자인을 언급해 넘어가서 전부 이해하는게 좋을거같다.</li>
<li>리덕스를 배우고나면 아토믹디자인이 너무 깔끔해질거같은 생각. </li>
</ol>
<h3 id="3-회원가입과-로그인-사이트-구현">3. 회원가입과 로그인 사이트 구현</h3>
<blockquote>
<ul>
<li>프로젝트 기획상 프론트엔드가 보여줄만한 부분이 많이 없었다.
그래서 처음부터 해보고싶은 로그인과 회원가입 페이지에 시간을 투자했다.
CSS는 최대한 미루고 서버 연결관련과 인터랙티브 기능에 대해서 작업했다.</li>
</ul>
</blockquote>
<hr> 

<h4 id="k-1">K:</h4>
<p>회원가입과 로그인에서 시도한 결과물은 나쁘지 않았다. 이번 프로젝트로 어떻게 다뤄야할지도 알았고, 몇몇기능은 회원가입/로그인 폼에서 계속 사용가능한것이니. 토이프로젝트로 다시 만들어 사용해도 될거같다라는 생각을 했다. 특히 비슷한 기능을 많아 커스텀훅으로 포장해도 좋을것 같았다.<br>카카오톡 로그인 API 를 이용해서 카카오로그인 기능 구현도 괜찮았다.  </p>
<h4 id="p-1">P:</h4>
<ol>
<li>여기에 신경 쓰면 안됐다. 내가 회원가입과 로그인폼에 작업을 몰두한동안. 프론트 팀원도 다른것에 몰두하느라. 정작 프로젝트에 제일 중요한 핵심 기능의 프론트단이 완성되지 않았다.  </li>
<li>기본적은 CSS 는 만들어뒀어야했다. 나중에 몰아서 하겠단 생각으로 인터랙티브 기술만 하려다. 나중에 CSS 에서 허점이 많았다.</li>
<li>중간에 백엔드에서 제작한 카카오톡 로그인 API 는 JAVASCRIPT SDK 였기 떄문에 리액트환경에서는 사용하기 매우 어려웠다. 더군다나 시간이 걸리는 일이었으면, 내가 이어서 했으면 안됐다. 서버쪽이나 프론트쪽이나 어느곳에서든 연결할 수 있는거였으면, 백엔드 팀원이 마저 작업하던지 과감하게 삭제했어야했다.  <h4 id="t-2">T:</h4>
</li>
<li>로그인과 회원가입 페이지는 사용자가 제일 많이 방문하는 페이지중 하나 아닐까 싶다. 마이크로 인터랙션은 계속 유지하는게 좋을 것 같다.</li>
<li>핵심기능 먼저 구현하여 그 이후로 살을 붙이는 방법으로 페이지를 제작하는게 좋을 것 같다. 이 사이트에 핵심은 로그인/회원가입/인덱스가 아닌 채팅창이니... </li>
<li>카카오톡 API 사용방법은 이제 깨달았으니 다음 작업물에서는 온전히 사용할 수 있을것 같다. </li>
</ol>
<h2 id="그래서-">그래서 ?</h2>
<ul>
<li><p>이번 프로젝트를 통해서 알게된 정보들이 너무 많고, 내가 또 어떻게 해야할지 감이 잡힌 아주 소중한 프로젝트였다. 완성된 결과물보다 그 과정이 더중요한것같다. </p>
</li>
<li><p>다음글은  작업하면서 마주하게된 Error/Trouble과 해결/우회 방법을 기록하려한다. </p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[포스코X코딩온] 웹개발자 입문과정 9.2]]></title>
            <link>https://velog.io/@smurf_/%ED%8F%AC%EC%8A%A4%EC%BD%94X%EC%BD%94%EB%94%A9%EC%98%A8-%EC%9B%B9%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9E%85%EB%AC%B8%EA%B3%BC%EC%A0%95-9.2</link>
            <guid>https://velog.io/@smurf_/%ED%8F%AC%EC%8A%A4%EC%BD%94X%EC%BD%94%EB%94%A9%EC%98%A8-%EC%9B%B9%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9E%85%EB%AC%B8%EA%B3%BC%EC%A0%95-9.2</guid>
            <pubDate>Sat, 20 May 2023 07:43:53 GMT</pubDate>
            <description><![CDATA[<h1 id="redux">Redux</h1>
<h2 id="redux-사용-해보기">Redux 사용 해보기</h2>
<ul>
<li><p><code>npm i redux react-redux @reduxjs/toolkit</code> </p>
</li>
<li><p>index.js 수정</p>
<pre><code class="language-js">import {configureStore} from &quot;@reduxjs/toolkit&quot;;
import { Provider } from &quot;react-redux&quot;;</code></pre>
<p>configureStore : store 생성 함수.<br>Provider:  리액트 App.js 에 Store 를 손쉽게 연동 할 수 있도록 도와주는 컴포넌트  </p>
<h2 id="indexjs">index.js</h2>
<pre><code class="language-js">//index.js
//초기값
const intialState ={
number:0,
}
// Reducer 정의 : 변화를 일으키는 함수
const reducer = ( state = initialState,action) =&gt;{
switch (action.type){
  case&quot;INCREMENT&quot;:
        return{number:state.number +1};
  case&quot;DECREMENt&quot;:
        return{number:state.number -1};
  default:
    return state;
}
}


</code></pre>
</li>
</ul>
<p>const store = configureStore({ reducer: reducer }, composeWithDevTools());
const root = ReactDOM.createRoot(document.getElementById(&quot;root&quot;));
root.render(</p>
  <Provider store={store}>
    <App4 />
  </Provider>
);

<pre><code>* `npm i redux-devtools-extension` 를 설치해야 Chrome 에서 확장프로그램으로 redux를 확인 할 수 있다.

```js
//composeWithDevTools() : Chrome devtools에서 확인할 수 있음. 
const store = configureStore({ reducer: reducer }, composeWithDevTools());</code></pre><h2 id="appjs">App.js</h2>
<ul>
<li>useState 사용 및 props 전달 부분 다 삭제하기.</li>
</ul>
<pre><code class="language-jsx">import {useSelector,useDispatch} from &#39;react-redux&#39;;

const number = useSelector(state=&gt;state.number);
const dispatch = useDispatch();
&lt;button onClick={()=&gt;{dispatch({type:&#39;INCREASE&#39;})}}&gt;1증가&lt;/button&gt;
&lt;button onClick={()=&gt;{dispatch({type:&#39;DECREASE&#39;})}}&gt;1감소&lt;/button&gt;</code></pre>
<ul>
<li>store에서 number를 가져와서 number로 할당, </li>
<li></li>
</ul>
<h2 id="기본-폴더-구조">기본 폴더 구조</h2>
<ul>
<li><strong>components 폴더</strong><br>DOM 마크업과 스타일 담당 / 데이터 처리 능력 없음 Redux와 관련 없음<br>부모 컴포넌트로 부터 받은 props인 데이터와 콜백(callback)을 사용한다.</li>
<li><strong>containers 폴더</strong><br>동작 로직 관련 / 데이터 처리능력 있어야함 / Redux와 관련이있는 부분<br>렌더링 되어야할 데이터를 props로 components 폴더 컴포넌트로 넘겨줌</li>
<li><strong>store 폴더 (or modules 폴더)</strong><br>State,Acion 타입 ,Action 생성 함수,reducer 코드등 리덕스 관련 코드를 모아두는 폴더</li>
</ul>
<p>ex)</p>
<pre><code class="language-js">// store/counter.js

export const increase = () =&gt; ({type:&#39;counter/INCREASE&#39;});
export const decrease = () =&gt; ({type:&#39;counter/DECREASE&#39;});

const initialState = {
  number:0
}
//reducer
function counter(state = initialState, action) {
  swtich(action.type){
    case &#39;counter/INCREASE&#39; {
        number: state.number + 1
          }
      case &#39;counter/DECREASE&#39;{
        number: state.number - 1
        }
    default:
        returm state;
      }
}
export default counter;</code></pre>
<h3 id="combinereducers">combineReducers</h3>
<ul>
<li>여러개의 리듀서를 하나로 합쳐준다.</li>
</ul>
<pre><code class="language-js">// store/index.js
import {combineReducers} from &#39;redux&#39;;
const rootReducer = combineReducers({
  counter});
export default rootReducer;</code></pre>
<p>음... 피드백환영</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[포스코X코딩온] 웹개발자 입문과정 9.1]]></title>
            <link>https://velog.io/@smurf_/%ED%8F%AC%EC%8A%A4%EC%BD%94X%EC%BD%94%EB%94%A9%EC%98%A8-%EC%9B%B9%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9E%85%EB%AC%B8%EA%B3%BC%EC%A0%95-9.1</link>
            <guid>https://velog.io/@smurf_/%ED%8F%AC%EC%8A%A4%EC%BD%94X%EC%BD%94%EB%94%A9%EC%98%A8-%EC%9B%B9%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9E%85%EB%AC%B8%EA%B3%BC%EC%A0%95-9.1</guid>
            <pubDate>Sat, 20 May 2023 05:15:34 GMT</pubDate>
            <description><![CDATA[<h1 id="redux">Redux</h1>
<ul>
<li>Redux 는 Javascript 상태관리 라이브러리</li>
<li>리액트에 자주사용하지만 Redux는 vanilla 에서도 사용 가능하다.</li>
<li>상태관리 라이브러리로 많이 사용</li>
</ul>
<h2 id="사용하는-이유">사용하는 이유</h2>
<ul>
<li>컴포넌트 수가 많은 대형 플젝에서는 state를 전해주기위해 props를 엄청나게 써야함</li>
<li>마치 콜백지옥같은 props hell , props drilling 을 맛보게됨(이미맛봄)</li>
<li><em>Redux*</em>는 전역으로 상태 관리를 할수 있게 되어 store라는곳에서 언제든지 꺼내 쓸 수 있음.</li>
</ul>
<h2 id="redux-용어-정리">Redux 용어 정리</h2>
<blockquote>
<ul>
<li>Store</li>
<li>Action</li>
<li>Reducer</li>
<li>dispatch</li>
</ul>
</blockquote>
<h2 id="store">Store</h2>
<ul>
<li>store 는 상태가 관리되는 오직 하나의 공간</li>
<li>스토어 안에는 현재 애플리케이션의 상태와 리듀서가 들어가 있음</li>
<li><strong>한 개의 프로젝트는 단 하나의 스토어만 가질수 있음</strong></li>
</ul>
<h2 id="action">Action</h2>
<ul>
<li>상태에 어떠한 변화가 필요하면 액션(action)이란 것이 발생&#39;</li>
<li>Action은 컴포넌트에서 store에 운반할 데이터를 말함.</li>
<li>action은 하나의 객체로 표현됨<pre><code class="language-js">{
type:&#39;CHANGE_INPUT&#39;,
text: &#39;안녕하세요&#39;,
}
{
  type:&#39;INCREASE&#39;,
}</code></pre>
</li>
</ul>
<h2 id="dispatch">Dispatch</h2>
<ul>
<li>액션(변화)를 <strong>발생</strong>시키는 것 </li>
<li>dispatch(action) 과 같은 형태로 액션 객체를 파라미터로 넣어서 호출..</li>
</ul>
<h2 id="reducer">Reducer</h2>
<ul>
<li>리듀서는 액션 type 에 따라 변화를 일으키는 함수</li>
<li>첫번 째 매개변수는 초기 상태 값이고</li>
<li>두번 째 매개변수는 Action 값임.<pre><code class="language-js">const initialState = {
counter:1
}
</code></pre>
</li>
</ul>
<p>function reducer(state=initialState,action){
  switch(action.type){
    case &#39;INCREMENT&#39;:
      return { 
        counter: state.counter +1
  };
    default:
      return state;
  }</p>
<pre><code>### 정리
* Store 에는 Reducer 와 상태 값이 있음 
* Reducer는 액션.type에 따라 변화를 일으키는 함수임.
* Action은 어떠한 상태가 변화가 필요할때 발생하는 이벤트. 컴포넌트에서 사용자에게 상호작용을 받아 
액션이 만들어져서 스토어로 전달 함.
* Dispatch : 컴포넌트에서 액션을 만들기 위해 사용하는 것. 

&lt;hr&gt;

예 ) 아이디/비밀번호를 사용자가 로그인 하여 버튼을 클릭 했을때
0. action을 만든다. login함수를 만들어 , 아이디 비밀번호 값을 받고 액션타입을 지정해준다.
`function login(username, password) {
  return {
    type: &#39;LOGIN&#39;,
    payload: {
      username: username,
      password: password
    }
  };
}
`

1.버튼의 onClick 함수에 아이디/비밀번호 값을 action 으로 감싸 dispatch로 action을 보낸다
`const action = login(username, password);
    dispatch(action);`
2. dispatch로 보낸 action은 reducer가 받는다. 이때 reducer는 초기값의 state와 action 이 파라미터다. reducer 에서는 action.type 에 맞춰 적절하게 코드가 실행된다.

3. 이때. reducer에서는 불변성을위해 첫번째 파라미터 state를 항상 spread로 복사해준다 .





맞나.... 틀린점 피드백 감사하겠습니다. </code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[내가 답답해서 적어두는 리액트에서 쓰는 Lottie 색상바꾸기 ]]></title>
            <link>https://velog.io/@smurf_/%EB%82%B4%EA%B0%80-%EB%8B%B5%EB%8B%B5%ED%95%B4%EC%84%9C-%EC%A0%81%EC%96%B4%EB%91%90%EB%8A%94-%EB%A6%AC%EC%95%A1%ED%8A%B8%EC%97%90%EC%84%9C-%EC%93%B0%EB%8A%94-Lottie-%EC%83%89%EC%83%81%EB%B0%94%EA%BE%B8%EA%B8%B0</link>
            <guid>https://velog.io/@smurf_/%EB%82%B4%EA%B0%80-%EB%8B%B5%EB%8B%B5%ED%95%B4%EC%84%9C-%EC%A0%81%EC%96%B4%EB%91%90%EB%8A%94-%EB%A6%AC%EC%95%A1%ED%8A%B8%EC%97%90%EC%84%9C-%EC%93%B0%EB%8A%94-Lottie-%EC%83%89%EC%83%81%EB%B0%94%EA%BE%B8%EA%B8%B0</guid>
            <pubDate>Wed, 10 May 2023 19:27:52 GMT</pubDate>
            <description><![CDATA[<ul>
<li><p>json 파일에서 ty: fl 부분을찾아 K 배열을 변경한다.
[R,G,B] 이며 , 0-255범위가 아닌, 0-1의 범위를 갖고있다 ( 0.74 , 0.23,1 등)</p>
<pre><code class="language-json">{
ty: &quot;fl&quot;,
c: {
 a: 0,
 k: [
   0,
   0,
   0,
 1
 ]
},
o: {
 a: 0,
 k: 100
},
nm: &quot;Fill 1&quot;,
mn: &quot;ADBE Vector Graphic - Fill&quot;
},</code></pre>
</li>
<li><p>lottie-colorify 패키지 설치</p>
</li>
</ul>
<ol>
<li>패키지 설치<pre><code>npm i lottie-colorify </code></pre></li>
<li>lottie-colorify 임포트하기 
임포트 위치는 LottieComponent ( 전글 참고 )<pre><code>import Lottie from &#39;lottie-web&#39;;
import { colorify,replaceColor,flatten,getColors } from &#39;lottie-colorify&#39;;
import SomeAnimation from &#39;./SomeAnimation.json&#39;;</code></pre></li>
<li>Lottie 컴포넌트에서 작성하면된다</li>
</ol>
<pre><code class="language-js">// 1. colorify : 색상을 변경 ( 원하는 색상 배열에 넣기 ) 
import Lottie from &#39;lottie-web&#39;;
import { colorify } from &#39;lottie-colorify&#39;;
import SomeAnimation from &#39;./SomeAnimation.json&#39;;

const animation = Lottie.loadAnimation({
  container: container.current,
  animationData: colorify([&#39;#ef32d0&#39;, [50, 100, 200], &#39;#fe0088&#39;], SomeAnimation),
});</code></pre>
<pre><code class="language-js">// 2. replaceColor : 단일색상 변경하기 ( A 를 B로 )
import Lottie from &#39;lottie-web&#39;;
import { replaceColor } from &#39;lottie-colorify&#39;;
import SomeAnimation from &#39;./SomeAnimation.json&#39;;

const animation = Lottie.loadAnimation({
  container: container.current,
  animationData: replaceColor(&#39;#ef32d0&#39;, &#39;#fe0088&#39;, SomeAnimation),
});</code></pre>
<pre><code class="language-js">// 3. 단색으로 통일하기 
import Lottie from &#39;lottie-web&#39;;
import { flatten } from &#39;lottie-colorify&#39;;
import SomeAnimation from &#39;./SomeAnimation.json&#39;;

const animation = Lottie.loadAnimation({
  container: container.current,
  animationData: flatten(&#39;#fe0088&#39;, SomeAnimation),
});</code></pre>
<pre><code class="language-js">//4. 현재색상 추출하기
import Lottie from &#39;lottie-web&#39;;
import { getColors } from &#39;lottie-colorify&#39;;
import SomeAnimation from &#39;./SomeAnimation.json&#39;;

console.log(getColors(SomeAnimation));</code></pre>
<pre><code class="language-js">// 5. 여러색상을 하나하나 바꾸기
// loadAnimation 을 호출 하기전 replaceColor를 이용해서 변경해준다.
let anim = loaded.json;
anim = replaceColor(&#39;#ff0000&#39;, &#39;#00ff00&#39;, anim);
anim = replaceColor(&#39;#0000ff&#39;, &#39;#ff0000&#39;, anim);
anim = replaceColor(&#39;#00ff00&#39;, &#39;#0000ff&#39;, anim);


myAnim = lottie.loadAnimation({
  animationData: anim
});</code></pre>
<p>참고 : <a href="https://www.npmjs.com/package/lottie-colorify?activeTab=readme">https://www.npmjs.com/package/lottie-colorify?activeTab=readme</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[내가 답답해서 적어두는 리액트에서 쓰는 Lottie-Web]]></title>
            <link>https://velog.io/@smurf_/%EB%82%B4%EA%B0%80-%EB%8B%B5%EB%8B%B5%ED%95%B4%EC%84%9C-%EC%A0%81%EC%96%B4%EB%91%90%EB%8A%94-%EB%A6%AC%EC%95%A1%ED%8A%B8%EC%97%90%EC%84%9C-%EC%93%B0%EB%8A%94-Lottie-Web</link>
            <guid>https://velog.io/@smurf_/%EB%82%B4%EA%B0%80-%EB%8B%B5%EB%8B%B5%ED%95%B4%EC%84%9C-%EC%A0%81%EC%96%B4%EB%91%90%EB%8A%94-%EB%A6%AC%EC%95%A1%ED%8A%B8%EC%97%90%EC%84%9C-%EC%93%B0%EB%8A%94-Lottie-Web</guid>
            <pubDate>Wed, 10 May 2023 18:53:54 GMT</pubDate>
            <description><![CDATA[<p>react-lottie 패키지는 react 18을 지원을 안한다.</p>
<p>그래서 구글링후 lottie-react 받아 설치하니, 인터랙션이 작동을 안한다.</p>
<p>그래서 찾고찾아 찾은 <code>lottie-web</code> 패키지.</p>
<p>이건 <code>&lt;Lottie&gt;</code> 컴포넌트를 바로지원하지않아 본인이 직접만들어야함..</p>
<p>구글링해서 몇개 찾아봤는데 렌더링에서 이상하게 작동해서 svg 가 두번 렌더링된다던지
인터랙션이 안먹히는 오류가 있던가 해서.. 직접 만들어봄</p>
<ol>
<li>패키지 설치<pre><code>npm i lottie-web</code></pre></li>
<li>LottieComponent 생성 (복붙하면됨)<pre><code class="language-js">import React, { useState, useRef, useEffect } from &quot;react&quot;;
import Lottie from &quot;lottie-web&quot;;
</code></pre>
</li>
</ol>
<p>// Lottie 컴포넌트 정의
const LottieComponent = ({
  animationData,
  loop,
  autoplay,
  speed,
  isPaused,
  isStopped,
  ...restProps
}) =&gt; {
  // Lottie 애니메이션 컨테이너에 대한 ref
  const animationContainer = useRef(null);
  const [animationInstance, setAnimationInstance] = useState(null);</p>
<p>  // Lottie 애니메이션 로드 및 초기화
  useEffect(() =&gt; {
    // Lottie 애니메이션 옵션 설정
    const animationOptions = {
      container: animationContainer.current,
      renderer: &quot;svg&quot;,
      loop: loop !== undefined ? loop : true,
      autoplay: autoplay !== undefined ? autoplay : true,
      animationData: animationData,
      rendererSettings: {
        preserveAspectRatio: &quot;xMidYMid slice&quot;,
      },
    };</p>
<pre><code>// Lottie 애니메이션 로드
const animation = Lottie.loadAnimation(animationOptions);
// Lottie 애니메이션 상태 업데이트
setAnimationInstance(animation);

//  컴포넌트 unmount 시 애니메이션 제거
return () =&gt; {
  animation.destroy();
};</code></pre><p>  }, [animationData, loop, autoplay]);</p>
<p>  // Lottie 인터랙션 관리
  useEffect(() =&gt; {
    if (animationInstance !== null) {
      // isPaused 프롭스에따라 일시정지 / 실행
      if (isPaused) {
        animationInstance.pause();
      } else {
        animationInstance.play();
      }</p>
<pre><code>  if (isStopped) {
    animationInstance.stop();
  }

  if (speed !== undefined) {
    animationInstance.setSpeed(speed);
  }
}</code></pre><p>  }, [isPaused, isStopped, speed, animationInstance]);</p>
<p>  return &lt;div ref={animationContainer} {...restProps} /&gt;;
};</p>
<p>export default LottieComponent;</p>
<pre><code>
3. 부모컴포넌트에서 Lottie 컴포넌트 호출
```js
import Lottie from &quot;./LottieComponent&quot;;
import animationData from &quot;assets/loading.json&quot;;

.
.
.
          &lt;Lottie
            animationData={animationData}
            speed={speed}
            isPaused={isPaused}
            isStopped={isStopped}
          /&gt;
</code></pre><p><em>오류 피드백 환영합니다</em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[포스코X코딩온] 웹개발자 입문과정 8.2
]]></title>
            <link>https://velog.io/@smurf_/%ED%8F%AC%EC%8A%A4%EC%BD%94X%EC%BD%94%EB%94%A9%EC%98%A8-%EC%9B%B9%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9E%85%EB%AC%B8%EA%B3%BC%EC%A0%95-8.2</link>
            <guid>https://velog.io/@smurf_/%ED%8F%AC%EC%8A%A4%EC%BD%94X%EC%BD%94%EB%94%A9%EC%98%A8-%EC%9B%B9%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9E%85%EB%AC%B8%EA%B3%BC%EC%A0%95-8.2</guid>
            <pubDate>Thu, 27 Apr 2023 17:00:09 GMT</pubDate>
            <description><![CDATA[<h1 id="usestate">useState</h1>
<ul>
<li>리액트에서 상태가 변경될때 useState 훅을 사용한다.</li>
<li>상태가 변경된다는건.. <strong>값이 바뀔때</strong> (단순하게 생각)</li>
</ul>
<pre><code class="language-js">import React, { useState } from &quot;react&quot;;

//값을 불러오고

const [state,setState] =useState(초기값) 
// state명은 마음대로 지어도 된다. ( ex name,setName)
// set은 관습적으로 사용하는 듯 싶다.

// 초기값은 무엇이든지 들어간다.(0,&#39;0&#39;,[],...)
</code></pre>
<h2 id="usestate-를-통한-조건부-화면-출력">useState 를 통한 조건부 화면 출력</h2>
<ul>
<li>&amp;&amp; 와 같이사용해서 </li>
<li>토글 스위치 같이 사용 할 수 있다.<pre><code class="language-js">const [visible,setVisible] = useState(true)// 초기값을 보이게
.
.
.
const toggle = () =&gt; setVisible(!visible); // visible true면 &lt;=&gt; false로
</code></pre>
</li>
</ul>
<p>return (
  &lt;&gt; </p>
<p>  {visible &amp;&amp; (
   <h1> 갑자기 나타난 h1  </h1> 
  }
  &lt;/&gt;
)</p>
<pre><code>* visible 이 트루일때 h1 태그를 보여주고 visible 이 false 일때 h1 태그가 렌더링 되지 않는다.

### &amp;&amp; ?
* 논리연산자 AND &amp;&amp; 이다.
`A &amp;&amp; B` :  A 가 트루면 B도 트루다 (A가 폴스면 B도 없다)

### 배열 STATE에 추가하는법
* setState는 값을 **변경**해주기 떄문에, 배열에서는 새로운 값을 넣으면, 추가가 아닌 변경이 된다

```js
const [list,setList] = useState([1,2,3,4]);

setList([5]);

console.log(list) //[5]
</code></pre><p>이럴땐 spread 문법을 이용해서 추가해주면된다. (기존배열+신규값 이라 생각하자) </p>
<pre><code class="language-js">const [list2,setList2] =useState([1,2,3,4]);
setList([...list2,5]);

console.log(list2)//[1,2,3,4,5]</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[포스코X코딩온] 웹개발자 입문과정 8.1]]></title>
            <link>https://velog.io/@smurf_/%ED%8F%AC%EC%8A%A4%EC%BD%94X%EC%BD%94%EB%94%A9%EC%98%A8-%EC%9B%B9%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9E%85%EB%AC%B8%EA%B3%BC%EC%A0%95-8.1</link>
            <guid>https://velog.io/@smurf_/%ED%8F%AC%EC%8A%A4%EC%BD%94X%EC%BD%94%EB%94%A9%EC%98%A8-%EC%9B%B9%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9E%85%EB%AC%B8%EA%B3%BC%EC%A0%95-8.1</guid>
            <pubDate>Thu, 27 Apr 2023 16:38:55 GMT</pubDate>
            <description><![CDATA[<h1 id="rest">...rest</h1>
<ul>
<li>관례상 rest(단어)를 쓴다 <del>나머지니까</del><h2 id="객체에서의-rest">객체에서의 ...rest</h2>
</li>
<li>구조분해 할당을 통해서 사용할 수 있다.<pre><code class="language-js"></code></pre>
</li>
</ul>
<p>const me = {
    from : &quot;korea&quot;,
    language:&quot;korean&quot;,
    hobby:&quot;movie&quot;,
      phone:&quot;010-1234-5678&quot;,
    }</p>
<p>const { from,language,hobby,phone } = me; // 구조분해 할당</p>
<p>console.log(phone)//&quot;010-1234-5678&quot;</p>
<pre><code>이 때 `const {from, ...rest} = me;` 를 하게 되면,
```js
console.log(rest)//  {language ...,hobby...,phone...,} </code></pre><p>from을 제외한 나머지값들이 rest에 저장돼 출력 된다. </p>
<blockquote>
<p><strong>...rest를 이용해서</strong>
<strong>me 객체에서 원하는 정보를 제외하고 보낼 수 있다.</strong>  </p>
</blockquote>
<ul>
<li>me 객체에서 개인정보인 phone 을 빼고 보여주고 싶을때<pre><code class="language-js">const {phone,...withoutphone} //rest 써두됨....
console.log(withoutphone)</code></pre>
프론트단에서 정보를 보여줄 때, 다른사이트로 넘길 때 필요하지 않은 정보는 제외하고 넘길 수 있다.</li>
</ul>
<h2 id="배열에서의-rest">배열에서의 ...rest</h2>
<ul>
<li>위랑 비슷하다 </li>
</ul>
<pre><code class="language-js">const myfriends=[&quot;leo&quot;,&quot;cola&quot;,&quot;game&quot;] // :sad:

// const friend1 = myfriend[0]
// const friend2 = myfriend[1]
// const friend3 = myfriend[2]

const [friend1,friend2,friend3] = myfriends

// or 


const [friend1,...rest] = myfriends</code></pre>
<h2 id="rest-를-파라미터로-쓸-때-함수">...rest 를 파라미터로 쓸 때 (함수)</h2>
<ul>
<li>spread문법과 동일하게 매개변수 앞에 ...같이 쓴다.</li>
</ul>
<pre><code class="language-js">
function number = (one,two,three) {
  console.log(one,two,three) //1,2,3
}

  number(1,2,3)

function number = (one,...rest) {
  console.log(one)//1
  console.log(rest)//[2,3]
}
// 이 때, rest 는 배열의 형태로 나타낸다</code></pre>
<ul>
<li><strong>파라미터의 개수를 안 정해도 된다 (<del>타입스크립트 : ?</del>)</strong></li>
</ul>
<pre><code class="language-js">function number = (one,...rest) {
  console.log(rest)//[2,3,4,5,6,7,8,9]
}
number(1,2,3,4,5,6,7,8,9)</code></pre>
<ul>
<li><strong>위와 비슷한 특성 때문에 특정 값만 따로 추출할 수 있다.</strong><pre><code class="language-js">function me = (phone,...rest) {
console.log(rest) // korean,korea,...
}
me(01012345678,korean,korea, ...,)
</code></pre>
</li>
</ul>
<pre><code>
## ...rest 를 이용한 응용방법

* react상에서 자주 사용할 것같은 응용법

```js
//app.jsx
&lt;PasswordInput
type=&#39;password&#39;
value={value}
onChange={onChange}
isValid={isValid}
&gt;
//PasswordInput.jsx

export default const PasswordInput = ({isValid,...rest}) =&gt;{
   //isValid 만 가져와서, 유효성 검사를 한다.
   if (!isValid) return;

   return 
  &lt;input {rest}&gt; // rest를 이용해서 input 태그의 속성을 그대로 넣을 수 있다.

 }</code></pre><ul>
<li>익숙해진다면 가독성 좋고 간결한 코드 작성이 될 수 있을듯 하다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[포스코X코딩온] 웹개발자 입문과정 7.2]]></title>
            <link>https://velog.io/@smurf_/%ED%8F%AC%EC%8A%A4%EC%BD%94X%EC%BD%94%EB%94%A9%EC%98%A8-%EC%9B%B9%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9E%85%EB%AC%B8%EA%B3%BC%EC%A0%95-7.2-mlem3b8r</link>
            <guid>https://velog.io/@smurf_/%ED%8F%AC%EC%8A%A4%EC%BD%94X%EC%BD%94%EB%94%A9%EC%98%A8-%EC%9B%B9%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%9E%85%EB%AC%B8%EA%B3%BC%EC%A0%95-7.2-mlem3b8r</guid>
            <pubDate>Thu, 20 Apr 2023 10:17:14 GMT</pubDate>
            <description><![CDATA[<h1 id="socketio">Socket.io</h1>
<ul>
<li><p><strong>socket.io</strong> 를 알아보고 채팅 서비스를 구현해보았다.
처음엔 양쪽 모두 확인해야해서 많이 어지러웠지만, 익숙해지니 어떤 흐름인지 차츰 보이기 시작했다.</p>
<p>socket.io를 응용하기 위해 토이 프로젝트인 채팅방 구현에서
기존에 사용중이던  디스코드 / 슬랙 중 채팅메시지 반응 버튼들이 재밌어서 
채팅에대한 답변/반응을 애니메이션으로 구현하고자 했다.</p>
</li>
<li><p>또 닉네임 설정과 채팅방 페이지를 다르게 구현해보려 했다.</p>
</li>
</ul>
<h2 id="기술">기술</h2>
<ol>
<li><h3 id="pageindex-pageindex">page(index page/index)</h3>
<blockquote>
<h4 id="-닉네임-입력">* <strong>닉네임 입력</strong></h4>
<p>//* 닉네임 입력후 입장시 2page 이동 *</p>
<h4 id="-랜덤닉네임-생성">* <strong>랜덤닉네임 생성</strong></h4>
<p> //* 단어 배열에서 랜덤하게 가져오기*</p>
</blockquote>
</li>
<li><h3 id="page-main-pagechat">page (main page/chat)</h3>
<blockquote>
<h4 id="-기본적인-채팅기능--양방향-송신-✔️">* 기본적인 채팅기능 / 양방향 송신 ✔️</h4>
<p>/</p>
<h4 id="-현재-접속자-리스트-✔️">* 현재 접속자 리스트 ✔️</h4>
<p>// <em>접속시도한 유저들마다 닉네임을 저장하여 화면에 출력</em></p>
<h4 id="-대화풍선의-리액션-기능-✔️">* 대화풍선의 리액션 기능 ✔️</h4>
<p>// *채팅 말풍선 호버시 말풍선의 인터랙션 기능 *</p>
<h4 id="-대화삭제">* 대화삭제</h4>
<p>// <em>채팅 클릭시 작성한 대화삭제기능 (삭제됨으로변경 or 말풍선 삭제)</em></p>
<h4 id="-사용자-추방">* 사용자 추방</h4>
<p>// *접속자 리스트에서 닉네임 클릭시 추방/1page 이동시키기 *</p>
<h4 id="-사용자-대화-무시">* 사용자 대화 무시</h4>
<p>// <em>접속자 리스트 - 닉네임 클릭시 사용자 대화 무시</em></p>
<h4 id="-이미지-업로드">* 이미지 업로드</h4>
<p>/</p>
<h4 id="-대화글-공지사항">* 대화글 공지사항</h4>
<p>// <em>채팅 말풍선 클릭시 작성한 대화 상단에 고정</em></p>
<h4 id="-유저-주목">* 유저 주목</h4>
<p>// *말풍선 클릭시 올린 상대의 배경화면 변경(유지)</p>
</blockquote>
</li>
</ol>
<h2 id="트러블-슈팅">트러블 슈팅</h2>
<p><img src="https://velog.velcdn.com/images/smurf_/post/7ffecdf7-bd0e-4bc0-ac42-99730fb0632f/image.png" alt=""></p>
<pre><code> // 완성된 리액션 탭? 인터랙션 바?</code></pre><h3 id="마우스-호버--마우스-클릭-">마우스 호버 ? 마우스 클릭 ?</h3>
<blockquote>
<p>원래 계획 : 마우스 클릭시 탭 토글, 채팅 메세지 마우스 아웃 시 사라지게</p>
</blockquote>
<p>마우스 토글과 마우스아웃을 동일하게 설정하였지만, 마우스가 탭에 들어가는순간
채팅 메세지밖으로나오면서, 바가 사라지게 되는 현상이 있었다.</p>
<p>HTML구조가 잘못되어 (설계 미스 ) 
<img src="https://velog.velcdn.com/images/smurf_/post/0c2588d2-da27-432a-9ca1-45559a84c91f/image.png" alt="">
위와 같이 변경하여, 인터랙션 바에 마우스엔터가 정상작동할 수 있었다.
그치만 UX 상, 뭔가 불편함을 느끼고 통일감이 없어서 같은 레이아웃을 유지한 채, hover out으로 변경하였다. 
모바일 상에서는 hover가 작동안하니, touch event 나 click 으로 다시 변경 할지 고민중</p>
<h3 id="애니메이션을-전달-">애니메이션을.. 전달 ?</h3>
<ul>
<li>인터랙션 바에 버튼을 클릭시, 말풍선이 움직인다 !   </li>
</ul>
<p>생각만해도 재밌다. 상대방 메세지에 반응을 해준다면, 화면 속 대화 출력을 넘어서, 생동감 넘치는 대화창을 구현 하고 싶었다.</p>
<p> 시간상, 원하는 애니메이션을 css로 구현하기보단 간단한 animate css 를 이용하였고,
 인터랙션 바에서 버튼을 클릭시, 해당 인터랙션바의 말풍선이 움직여야하니.
 this.parentNode를 이용해서 말풍선을 찾은뒤
 animate class 를 부여하여 동작하게 하였다.
 당사자 A. 화면에서는 생각대로 작동을 잘 하였고 어떤 문제도 없었다.<br> 어떤 애니메이션을 확인하기 위해 서버에게도,클래스명을 객체로 전달하여, 상대방 화면에서도 해당 말풍선이 흔들리게 하였다.</p>
<p>** 안되요 **</p>
<p>A 화면에서는 잘 작동하는것을, B화면에서는 꿈쩍도 하지 않았다.
그와 동시에 A화면에서는 더미 데이터가 아닌 동적 메시지는 작동하지 않았다.</p>
<h3 id="내가-클릭한게-뭐게">내가 클릭한게 뭐게~?</h3>
<p>생각해보니깐 화면에서 클릭한 말풍선은 시각적으론 알수 있었지만,
서버에선 보낸 애니메이션이 어떤 말풍선에 해당 하는지 알 수 없었다.
<img src="https://velog.velcdn.com/images/smurf_/post/f5f26997-3ad5-4936-84f9-46a9ac58bfa7/image.png" alt=""></p>
<pre><code>        아 ... </code></pre><p>데이터상으로는 내가 <strong>어떤 메시지</strong>에 애니메이션 요청을 보냈는지. 내가보낸 객체 데이터로는 알 수 없었다.</p>
<p>처음 시도했던, 내가 클릭한 대상 ( this ) 자체를 서버에 보내니, undefined로 받게되었고. 결과는 <strong>안되요</strong>..</p>
<p>조금 더 생각한 뒤 떠오른 아이디어는,
인터랙션 바에서 애니메이션을 보내는 행위(클릭), 클릭이벤트 일때, 내가 어떤 말풍선을 클릭했는지 알수 있게 id를 등록하여 보내주는것이었다.</p>
<p>( 말풍선에 이름을 달아 상대방한테 보내보자)</p>
<p>작동시켜보니 결과는 또 <strong>안되요</strong></p>
<p>흠.. 생각해보니 id 자체는 화면에서 지정하여 보냈기 때문에 다른 유저들은 해당 말풍선의 id 값을 갖고 있지 않았다. </p>
<p>아 그럼 ? <strong>메시지를 작성할때 만들어주면 되겠네!!</strong>
...</p>
]]></description>
        </item>
    </channel>
</rss>