<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hye_ona.log</title>
        <link>https://velog.io/</link>
        <description>나아가는 OnlyOne 개발자</description>
        <lastBuildDate>Mon, 29 May 2023 07:30:29 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>hye_ona.log</title>
            <url>https://velog.velcdn.com/images/ve_hye_ona/profile/45cc7b76-78ce-4a6a-bfc5-41b73dbd528b/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. hye_ona.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ve_hye_ona" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Server-side rendering과 Client-side rendering]]></title>
            <link>https://velog.io/@ve_hye_ona/Server-side-rendering%EA%B3%BC-Client-side-rendering</link>
            <guid>https://velog.io/@ve_hye_ona/Server-side-rendering%EA%B3%BC-Client-side-rendering</guid>
            <pubDate>Mon, 29 May 2023 07:30:29 GMT</pubDate>
            <description><![CDATA[<p>다음의 문제에 대한 해결을 위해 해당 글을 포스팅한다.</p>
<ol>
<li>왜 server-side rendering과 client-side rendering 중 하나를 선택해야 할까?</li>
<li>server-side rendering과 client-side rendering의 차이는 무엇인가?</li>
<li>pre-rendering은 무엇인가?</li>
<li>server-side rendering과 client-side rendering 방식 각각의 장단점은 무엇인가?</li>
<li>어떠한 프로젝트에 어떠한 rendering 방법을 적용하여야 할까?</li>
</ol>
<h1 id="rendering">Rendering</h1>
<p>사용자가 사이트에 접속하면 브라우저는 화면을 출력하기 위해 서버에 html, js 파일을 요청하여 브라우저 DOM에 그려주는데 이러한 전 과정을 렌더링이라고 한다.
즉, 렌더링 과정은 작성한 html, css, javascript 파일을 브라우저 화면으로 출력하는 과정이다.
개발자 측면에서는 웹/앱의 코드를 사용자와 상호작용할 수 있는 인터페이스인 브라우저와 사용자의 화면에 보여주게끔하는 과정이다.</p>
<p>여기에는 대표적으로 js 언어가 사용되고, 새로운 라이브러리나 프레임워크가 만들어지며 다양화된 웹사이트를 좀 더 효율적으로 보여주고자 만들어진 Client-side rendering, 그리고 WWW(World Wide Web)이 처음 출범했을 때 브라우저에 사용되었던 Server-side rendering의 2가지 종류가 있다.
실제로 Client-side rendering은 React에서 주로 사용되고 있고, Server-side rendering은 새로 떠오르고 있는 Next.js에서 주로 사용되고 있는 방식이다. </p>
<h3 id="rendering-방식-선택의-중요성">Rendering 방식 선택의 중요성</h3>
<p>웹 개발자는 화면을 개발할 때 어떠한 웹 서비스를 개발할지에 따라 적절한 웹 앱 아키텍처를 설계하고 적절한 tool과 기술을 사용해야 하는데, 렌더링 종류도 그 중 하나의 결정사안이 될 수 있다.
렌더링 종류를 개발할 웹 서비스에 맞게 잘 선택해야지만, SEO 결과, 앱 성능, 사용자 경험 등의 측면에서 나쁜 결과를 초래하지 않는, 그래서 이후 추가 개발 비용이 들지 않을 수 있는 서비스를 완성할 수 있다고 생각한다. </p>
<h2 id="server-side-rendering-ssr-vs-client-side-rendering-csr">Server-side rendering (SSR) VS Client-side rendering (CSR)</h2>
<h3 id="ssr">SSR</h3>
<p><strong>app의 코드가 server에서 process(render)되는 것</strong>이 특징이고 다음의 렌더링 과정을 거친다.</p>
<ol>
<li>유저가 브라우저의 주소창에 원하는 URL을 입력한다.</li>
<li>해당 URL에 대한 요청 데이터가 server에 전달된다.</li>
<li>server는 front-end/브라우저에서 필요한 데이터와 css 파일과 함께 html 파일을 생성한다.</li>
<li>server는 생성한 html 파일을 브라우저의 요청에 대한 응답으로 전송한다.</li>
<li>브라우저는 받은 html 파일을 실행하고 페이지에 표시한다.
<img src="https://velog.velcdn.com/images/ve_hye_ona/post/3374e352-92d1-450e-a4c1-0ca5c0c21772/image.png" alt=""></li>
</ol>
<h4 id="장점">장점</h4>
<ul>
<li><p>처음 load하는 시간이 빠르다.</p>
<ul>
<li>server의 브라우저의 요청에 대한 page 응답이 rendered html 파일이기 때문에, 브라우저에서는 javascript 파일을 실행시킬 필요가 없이 바로 결과를 화면에 보여줄 수 있다.</li>
</ul>
</li>
<li><p><strong>검색환경최적화(SEO)에 유리</strong>하다.</p>
<ul>
<li>search engine 상위 결과에 노출되려면 웹사이트는 검색엔진 웹 크롤러에 의해 readable해야 한다. 그러기 위해서 웹 사이트의 모든 정보를 텍스트 형태로 표시되어야 한다.</li>
<li>또한 웹사이트의 response time도 랭킹에 영향을 미친다. 그러한 측면에서 client-rendered 웹사이트에 비해 server-rendered 웹사이트에 걸리는 웹크롤러의 response time이 더 빠르다.</li>
</ul>
</li>
</ul>
<h4 id="단점">단점</h4>
<ul>
<li><p>server의 부하가 크다.</p>
<ul>
<li>SSR의 특성상 server의 자원을 사용하기 때문에 많은 요청이 들어오면 느려질 수 있다.</li>
<li>이러한 문제를 피하기 위해, 유저 수와 웹사이트 load capacity에 따라 적절한 조건의 hosting server를 선택하여야 한다.</li>
</ul>
</li>
<li><p>page의 데이터가 변하는 경우(페이지 전환)에는 그 속도가 느리다. </p>
<ul>
<li>유저가 server-rendered 페이지를 바꾸어야 하는 경우, 그 변화의 크고 작은 정도와 관련 없이 server가 다시 render하는 과정이 필요하다. </li>
</ul>
</li>
</ul>
<h3 id="csr">CSR</h3>
<p><strong>app의 코드가 사용자의 browser에 전송되어 process(render)</strong>되는 것이 특징이고 다음의 렌더링 과정을 거친다.</p>
<ol>
<li>유저가 브라우저의 주소창에 원하는 URL을 입력한다.</li>
<li>해당 URL에 대한 요청 데이터가 server에 전달된다.</li>
<li>server는 database로부터 정보를 끌어와 JSON 등의 요청된 형태로 응답을 생성한다.</li>
<li>server는 client에 요청된 데이터를 전송한다.</li>
<li>브라우저는 html 코드에 server로부터 얻은 데이터를 넣어 화면을 보여주고, client에 저장되어 있던 javascript를 실행하여 유저에게 페이지를 보여줄 수 있게 된다.
<img src="https://velog.velcdn.com/images/ve_hye_ona/post/284d81d5-dfa4-4dfb-8d78-454c2fc5cb27/image.png" alt=""></li>
</ol>
<h4 id="장점-1">장점</h4>
<ul>
<li><p>server의 부하가 적다.</p>
</li>
<li><p>처음 load 이후에는 웹사이트 rendering 속도가 빠르다.</p>
<ul>
<li>새로 변경된 부분만 client-side에서 re-render되므로 속도가 빠르다. </li>
</ul>
</li>
</ul>
<h4 id="단점-1">단점</h4>
<ul>
<li><p>초기 loading 시간이 길다.</p>
</li>
<li><p>SEO에 불리하다.</p>
</li>
</ul>
<h3 id="use-case">Use Case</h3>
<h4 id="ssr-1">SSR</h4>
<p>SEO가 중요하고 변경이 잘 없는 웹사이트의 경우에는 서버 사이드 렌더링이 가장 좋은 선택이 될 수 있다.</p>
<p>ex. 온라인 마켓, e-learning </p>
<h4 id="csr-1">CSR</h4>
<p>변경이 잦은 dynamic 웹사이트의 경우 클라이언트 사이드 렌더링이 더 좋은 선택지가 될 수 있다.</p>
<p>ex. 온라인 메신저, 소셜 네트워크</p>
<h4 id="ssr--csr-함께-사용하기">SSR + CSR (함께 사용하기)</h4>
<h2 id="pre-rendering">Pre-rendering</h2>
<p>렌더링 과정을 빠르게 진행하기 위해, 브라우저에 rendering되기 전 먼저 rendering 과정을 진행하여 빠르게 화면을 보여주는 Pre-render이 있다.</p>
<p>해당 과정을 통해서 다음의 두 가지 이점을 얻을 수 있다.</p>
<ul>
<li><p>server response 시간이 빨라진다.</p>
<ul>
<li>server에서 client로부터 요청을 받으면 바로 응답(ex. static webpage skeleton; 기본 페이지 레이아웃)을 주고 나머지 데이터를 생성하고 전송하는 동안 유저는 로딩 페이지를 보게 된다.</li>
</ul>
</li>
<li><p>SEO 랭킹을 올릴 수 있다. </p>
<ul>
<li>static website element(ex. meta-data, meta-descriptions, web page structure)가 먼저 렌더링되면서 웹 크롤러가 먼저 렌더링된 데이터를 분석하고 더 높은 SEO 랭크에 올릴 수 있다.</li>
</ul>
</li>
</ul>
<h3 id="use-case-1">Use Case</h3>
<p>ex. facebook</p>
<h1 id="ref">Ref</h1>
<ul>
<li><a href="https://clockwise.software/blog/client-side-vs-server-side-vs-pre-rendering/">https://clockwise.software/blog/client-side-vs-server-side-vs-pre-rendering/</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Redux middleware와 Async Logic  및 Data Fetching]]></title>
            <link>https://velog.io/@ve_hye_ona/Redux-middleware%EC%99%80-Async-Logic-%EB%B0%8F-Data-Fetching</link>
            <guid>https://velog.io/@ve_hye_ona/Redux-middleware%EC%99%80-Async-Logic-%EB%B0%8F-Data-Fetching</guid>
            <pubDate>Sun, 02 Apr 2023 15:11:24 GMT</pubDate>
            <description><![CDATA[<p>Redux reducer는 side effects를 포함할 수 없다.</p>
<pre><code>side effects란 함수의 반환 값 외에 볼 수 있는 상태/동작의 모든 변경 사항이다.
Ex.
- 콘솔에 값 로깅
- 파일 저장
- 비동기 타이머 설정
- AJAX HTTP 요청
- 함수 외부에 존재하는 일부 상태를 수정하거나 함수에 대한 인수 변경
- 난수 또는 고유한 난수 id 생성</code></pre><p>이러한 Side effects는 Redux Middleware에서 수행될 수 있다.</p>
<p>대표적으로 상태에 관해 외부 Server에 http request로 받은 데이터를 fetch하여 들고오는 경우 비동기 처리를 하여야 한다.</p>
<h2 id="how">How?</h2>
<p>비동기 middleware 함수를 action 객체가 아니라 dispatch로 넘겨, dispatch 전에 middleware가 먼저 실행될 수 있도록 한다.</p>
<h3 id="async-data-flow">Async Data Flow</h3>
<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/5ed19a56-3df9-445a-882c-2b0cffd42cd3/image.png" alt=""></p>
<h3 id="redux-thunk-middleware">Redux Thunk Middleware</h3>
<p>Redux의 공식 async function middleware</p>
<h4 id="configure">Configure</h4>
<pre><code>npm install redux-thunk</code></pre><h3 id="redux-thunk-function">Redux Thunk Function</h3>
<p>dispatch와 getState를 인수로 받는 함수로, 어떤 Redux store가 사용되는지 알지 못하는 채로 비동기 로직을 미리 작성할 수 있다.</p>
<p>Ex.</p>
<pre><code>// index.js

import React from &#39;react&#39;
import ReactDOM from &#39;react-dom&#39;
import { Provider } from &#39;react-redux&#39;
import &#39;./index.css&#39;
import App from &#39;./App&#39;

import &#39;./api/server&#39;

import store from &#39;./store&#39;
import { fetchTodos } from &#39;./features/todos/todosSlice&#39;

store.dispatch(fetchTodos)

ReactDOM.render(
  &lt;React.StrictMode&gt;
    &lt;Provider store={store}&gt;
      &lt;App /&gt;
    &lt;/Provider&gt;
  &lt;/React.StrictMode&gt;,
  document.getElementById(&#39;root&#39;)
)</code></pre><pre><code>// store에 thunk 사용할 수 있도록 update

import { createStore, applyMiddleware } from &#39;redux&#39;
import thunkMiddleware from &#39;redux-thunk&#39;
import { composeWithDevTools } from &#39;redux-devtools-extension&#39;
import rootReducer from &#39;./reducer&#39;

const composedEnhancer = composeWithDevTools(applyMiddleware(thunkMiddleware))

// The store now has the ability to accept thunk functions in `dispatch`
const store = createStore(rootReducer, composedEnhancer)
export default store</code></pre><pre><code>// thunk function

import { client } from &#39;../../api/client&#39;

const initialState = []

export default function todosReducer(state = initialState, action) {
  switch (action.type) {
    // omit other reducer cases
    case &#39;todos/todosLoaded&#39;: {
      // Replace the existing state entirely by returning the new value
      return action.payload
    }
    default:
      return state
  }
}

// thunk function
export async function fetchTodos(dispatch, getState) {
  const response = await client.get(&#39;/fakeApi/todos&#39;)
  dispatch({ type: &#39;todos/todosLoaded&#39;, payload: response.todos })
}</code></pre><h3 id="ref">Ref</h3>
<p><a href="https://redux.js.org/tutorials/fundamentals/part-6-async-logic">https://redux.js.org/tutorials/fundamentals/part-6-async-logic</a></p>
<p><a href="https://redux.js.org/tutorials/fundamentals/part-7-standard-patterns">https://redux.js.org/tutorials/fundamentals/part-7-standard-patterns</a></p>
<p><a href="https://redux.js.org/tutorials/fundamentals/part-8-modern-redux">https://redux.js.org/tutorials/fundamentals/part-8-modern-redux</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React-Redux]]></title>
            <link>https://velog.io/@ve_hye_ona/React-Redux</link>
            <guid>https://velog.io/@ve_hye_ona/React-Redux</guid>
            <pubDate>Thu, 23 Mar 2023 15:24:33 GMT</pubDate>
            <description><![CDATA[<h1 id="redux">Redux</h1>
<p><strong>Action</strong> 이벤트를 사용하여 <strong>애플리케이션 상태를 관리</strong>하고 업데이트하기 위한 패턴 및 라이브러리</p>
<ul>
<li><p>모든 UI 프레임워크와 통합할 수 있고, React와 함께 가장 자주 사용된다.</p>
</li>
<li><p>독립형 JS 라이브러리이므로 UI 프레임워크가 없어도 사용 가능</p>
</li>
</ul>
<h4 id="왜-사용하나-">왜 사용하나 ?</h4>
<p>전역 상태가 예측 가능한 방식으로만 업데이트될 수 있도록  상태에 대한 중앙 집중식 저장소 역할을 한다.</p>
<p>아래의 그림과 같이 애플리케이션은 
State, 
현재 상태에 대한 UI인 View, 
사용자의 입력에 따라 앱에서 발생하는 이벤트와 State에서의 업데이트인 Trigger로 이루어져 있는데,
Redux는 공유된 상태가 있는 경우 이를 <strong>단방향 데이터 흐름</strong>으로 관리되게 함으로써,
상태 관리와 관련된 개념을 정의 및 분리하고 뷰와 상태 간의 독립성을 유지하는 규칙을 적용함으로써 코드에 더 많은 구조와 유지 관리성을 보장 받는다.</p>
<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/65540e81-e860-4d89-8bf0-3e6e96c89c8a/image.png" alt=""></p>
<h4 id="언제-사용할까-">언제 사용할까 ?</h4>
<p>공유 상태 관리를 처리하는데 도움이 되지만 배워야 할 개념과 작성해야 할 코드가 많다.
따라서 다음의 경우에 유용하다.</p>
<ol>
<li>앱의 여러 위치에서 필요한 많은 양의 애플리케이션 상태가 있다.</li>
<li>시간 경과에 따라 앱 상태가 자주 업데이트된다.</li>
<li>해당 상태를 업데이트하는 논리는 복잡할 수 있다.</li>
<li>앱에 중간/큰 규모의 코드베이스가 있으며 많은 사람들이 작업할 수 있다.</li>
</ol>
<h2 id="요소">요소</h2>
<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/8b1f73a2-1d87-4ee5-ab5e-5524964c3df1/image.png" alt=""></p>
<h3 id="action">Action</h3>
<p><strong>type *<em>필드가 있는 JS 객체로 애플리케이션에서 발생한 *</em>이벤트</strong></p>
<p>Ex.</p>
<pre><code>const addTodoAction = {
  type: &#39;todos/todoAdded&#39;,    // (기능)/(발생 이벤트)
  payload: &#39;Buy milk&#39;        // 추가 정보로 필수 아님    
}</code></pre><h3 id="reducer">Reducer</h3>
<p>현재 state와 Action 객체를 수신하고 필요한 경우 상태를 업데이트하는 방법을 결정하고 새 상태를 반환하는 함수</p>
<p><strong>(state, action) =&gt; newState</strong></p>
<h4 id="규칙">규칙</h4>
<ol>
<li><p>state 및 action 인수를 기반으로 새 상태 값만 계산한다.</p>
</li>
<li><p>기존 state를 수정할 수 없다. (<strong>상태 불변</strong>)</p>
<ul>
<li>따라서 기존 state의 복사본을 이용해 새 값으로 복사본을 업데이트한 다음 반환하는 형태로 구현된다.</li>
</ul>
</li>
<li><p>비동기 논리를 수행하거나 임의의 값을 계산하거나 다른 side effect를 일으키지 않아야 한다.</p>
<ul>
<li>store를 custom하기 위해 dispatch 시, <strong>middleware를 활용</strong>하여 side effect(Ex. 콘솔에 값 로깅, 파일 저장, 비동기 타이머 설정, AJAX HTTP 요청, 함수 외부의 상태 수정, 함수에 대한 인수 변경, 난수 생성)를 발생시킬 수 있다.</li>
</ul>
</li>
</ol>
<p>Ex.</p>
<pre><code>const initialState = { value: 0 }

function counterReducer(state = initialState, action) {
  // Check to see if the reducer cares about this action
  if (action.type === &#39;counter/incremented&#39;) {
    // If so, make a copy of `state`
    return {
      ...state,
      // and update the copy with the new value
      value: state.value + 1
    }
  }
  // otherwise return the existing state unchanged
  return state
}</code></pre><h3 id="store">Store</h3>
<p>애플리케이션의 <strong>전역 상태를 보관</strong>하는 컨테이너이자 JS 객체</p>
<h4 id="기능-및-특징">기능 및 특징</h4>
<p>Redux Store 내부에 보관된 상태를 직접 수정/변경하면 안 된다.
대신, 일반 작업 객체를 만든 다음 저장소에 작업을 보내(Action) 무슨 일이 일어났는지 알려주어 상태를 업데이트할 수 있다.
그 과정은 다음과 같다.</p>
<ol>
<li>Store에 Action이 발송</li>
<li>Store는 root Reducer 함수를 실행하고 이전 상태와 Action을 기반으로 새 상태를 계산</li>
<li>Store는 UI가 새 데이터로 업데이트될 수 있도록 상태가 업데이트되었음을 Subscriber에게 알림</li>
</ol>
<p>Ex.</p>
<pre><code>import { configureStore } from &#39;@reduxjs/toolkit&#39;

const store = configureStore({ reducer: counterReducer })

console.log(store.getState())
// {value: 0}</code></pre><h3 id="dispatch">Dispatch</h3>
<p><strong>업데이트하고 해당 state를 호출/전달</strong>하는 Redux store의 기능</p>
<p>Ex.</p>
<pre><code>store.dispatch({ type: &#39;counter/incremented&#39; })

console.log(store.getState())
// {value: 1}</code></pre><h3 id="selectors">Selectors</h3>
<p>store의 state 값에서 특정 정보를 추출하는 함수</p>
<p>Ex.</p>
<pre><code>const selectCounterValue = state =&gt; state.value

const currentValue = selectCounterValue(store.getState())
console.log(currentValue)
// 2</code></pre><h2 id="핵심-개념">핵심 개념</h2>
<ol>
<li><p>Single Source of Truth</p>
<ul>
<li>전역 state는 하나의 store에 객체로써 저장되어 있다.</li>
</ul>
</li>
<li><p>State is Read-Only</p>
<ul>
<li>state를 변경하는 유일한 방법은 action을 dispatch하는 것이다.</li>
</ul>
</li>
<li><p>Changes are Make with Pure Reducer Functions</p>
</li>
</ol>
<h2 id="dataflow">DataFlow</h2>
<h3 id="초기-설정">초기 설정</h3>
<ol>
<li>Redux 저장소는 루트 감속기 기능을 사용하여 생성됩니다.</li>
<li>store는 루트 리듀서를 한 번 호출하고 반환 값을 초기 state 값으로 저장합니다.</li>
<li>UI가 처음 렌더링되면 UI 구성 요소는 Redux 스토어의 현재 상태에 액세스하고 해당 데이터를 사용하여 무엇을 렌더링할지 결정합니다. 또한 향후 매장 업데이트를 구독하여 상태가 변경되었는지 알 수 있습니다.</li>
</ol>
<h3 id="업데이트">업데이트</h3>
<ol>
<li>사용자가 버튼을 클릭하는 것과 같이 앱에서 어떤 일이 발생합니다.</li>
<li>앱 코드는 다음과 같이 Redux 스토어에 작업을 전달합니다.
dispatch({type: &#39;counter/incremented&#39;})</li>
<li>store는 이전 state와 현재 state로 감속기 기능을 다시 실행 action하고 반환 값을 새 것으로 저장합니다.</li>
<li>store은 등록된 UI의 모든 부분에 상점이 업데이트되었음을 알립니다.</li>
<li>스토어의 데이터가 필요한 각 UI 구성 요소는 필요한 상태 부분이 변경되었는지 확인합니다.</li>
<li>변경된 데이터를 보는(dispatch) 각 구성 요소는 새 데이터로 강제로 다시 렌더링하므로 화면에 표시되는 내용을 업데이트할 수 있습니다.</li>
</ol>
<h1 id="react-redux">React-Redux</h1>
<p>React의 공식 Redux UI 바인딩 라이브러리</p>
<pre><code>npm install react-redux</code></pre><h2 id="react-redux-hook">React-Redux Hook</h2>
<h3 id="useselector">useSelector</h3>
<p>React 구성 요소가 Redux store에서 데이터를 읽을 수 있게 해줌 (Redux store -&gt; React element)</p>
<ul>
<li><p>선택자를 인수로 가짐</p>
</li>
<li><p>선택자는 전체 Redux 상태를 인수로 사용하고 상태에서 일부 값을 읽고 해당 결과를 반환하는 함수</p>
</li>
<li><p><strong>자동으로 Redux store를 구독</strong>하고 action이 생길 때마다 useSelector를 다시 실행한다.</p>
</li>
<li><p>useSelector에 의해 반환된 값이 마지막으로 실행되었을 때 변경된 경우, <strong>새로운 참조 데이터(===)</strong>가 다시 렌더링되도록 한다.</p>
<ul>
<li>배열 state인 경우 성능적인 문제가 있을 수 있다. 따라서 React.memo()를 wrapping하여 실제로 상태가 변경되었을 때만 재렌더링하거나, 배열에서 id 배열만 읽도록 하고 해당 id를 props로 전달하는 방법이 있다(* 참조).</li>
</ul>
</li>
<li><p>한 Component에서 여러 개의 useSelector를 호출할 수 있다.</p>
</li>
</ul>
<p>Ex.</p>
<pre><code>import React from &#39;react&#39;
import { useSelector } from &#39;react-redux&#39;
import TodoListItem from &#39;./TodoListItem&#39;

const selectTodos = state =&gt; state.todos            // 선택자

const TodoList = () =&gt; {
  const todos = useSelector(selectTodos)

  // since `todos` is an array, we can loop over it
  const renderedListItems = todos.map(todo =&gt; {
    return &lt;TodoListItem key={todo.id} todo={todo} /&gt;
  })

  return &lt;ul className=&quot;todo-list&quot;&gt;{renderedListItems}&lt;/ul&gt;
}

export default TodoList</code></pre><p>Ex * .</p>
<pre><code>import React from &#39;react&#39;
import { useSelector, shallowEqual } from &#39;react-redux&#39;
import TodoListItem from &#39;./TodoListItem&#39;

const selectTodoIds = state =&gt; state.todos.map(todo =&gt; todo.id)

const TodoList = () =&gt; {
  const todoIds = useSelector(selectTodoIds, shallowEqual)

  const renderedListItems = todoIds.map(todoId =&gt; {
    return &lt;TodoListItem key={todoId} id={todoId} /&gt;
  })

  return &lt;ul className=&quot;todo-list&quot;&gt;{renderedListItems}&lt;/ul&gt;
}</code></pre><pre><code>import React from &#39;react&#39;
import { useSelector, useDispatch } from &#39;react-redux&#39;

import { availableColors, capitalize } from &#39;../filters/colors&#39;

const selectTodoById = (state, todoId) =&gt; {
  return state.todos.find(todo =&gt; todo.id === todoId)
}

// Destructure `props.id`, since we only need the ID value
const TodoListItem = ({ id }) =&gt; {
  // Call our `selectTodoById` with the state _and_ the ID value
  const todo = useSelector(state =&gt; selectTodoById(state, id))
  const { text, completed, color } = todo

  const dispatch = useDispatch()

  const handleCompletedChanged = () =&gt; {
    dispatch({ type: &#39;todos/todoToggled&#39;, payload: todo.id })
  }

  // omit other change handlers
  // omit other list item rendering logic and contents

  return (
    &lt;li&gt;
      &lt;div className=&quot;view&quot;&gt;{/* omit other rendering output */}&lt;/div&gt;
    &lt;/li&gt;
  )
}

export default TodoListItem</code></pre><h3 id="usedispatch">useDispatch</h3>
<p>Component에서 Redux store로 action을 dispatch하여 그 결과를 제공함
(Redux store &lt;- React element)</p>
<ul>
<li>실제 store.dispatch 함수를 반환한다.</li>
</ul>
<p>Ex.</p>
<pre><code>import React, { useState } from &#39;react&#39;
import { useDispatch } from &#39;react-redux&#39;

const Header = () =&gt; {
  const [text, setText] = useState(&#39;&#39;)
  const dispatch = useDispatch()

  const handleChange = e =&gt; setText(e.target.value)

  const handleKeyDown = e =&gt; {
    const trimmedText = e.target.value.trim()
    // If the user pressed the Enter key:
    if (e.key === &#39;Enter&#39; &amp;&amp; trimmedText) {
      // Dispatch the &quot;todo added&quot; action with this text
      dispatch({ type: &#39;todos/todoAdded&#39;, payload: trimmedText })
      // And clear out the text input
      setText(&#39;&#39;)
    }
  }

  return (
    &lt;input
      type=&quot;text&quot;
      placeholder=&quot;What needs to be done?&quot;
      autoFocus={true}
      value={text}
      onChange={handleChange}
      onKeyDown={handleKeyDown}
    /&gt;
  )
}

export default Header</code></pre><h3 id="store-provider">Store Provider</h3>
<p>React-Redux hook가 올바른 Redux store를 찾는 위치와 방법으로,
Component에서 사용하려는 store를 React-Redux에 알려주어 React Component에서 store를 사용할 수 있도록 한다.</p>
<ul>
<li><App> Component에 Redux store를 props로 가진 <Provider>를 전달한다.</li>
</ul>
<p>Ex.</p>
<pre><code>import React from &#39;react&#39;
import ReactDOM from &#39;react-dom&#39;
import { Provider } from &#39;react-redux&#39;

import App from &#39;./App&#39;
import store from &#39;./store&#39;

ReactDOM.render(
  // Render a `&lt;Provider&gt;` around the entire `&lt;App&gt;`,
  // and pass the Redux store to as a prop
  &lt;React.StrictMode&gt;
    &lt;Provider store={store}&gt;
      &lt;App /&gt;
    &lt;/Provider&gt;
  &lt;/React.StrictMode&gt;,
  document.getElementById(&#39;root&#39;)
)</code></pre><h2 id="react-redux-patterns">React-Redux Patterns</h2>
<ul>
<li><p>Global State -&gt; Redux Store</p>
</li>
<li><p>로컬한 Component State -&gt; React Component</p>
</li>
<li><p>edit의 과정에서가 아니라 edit 완료 후 state를 store에 update한다.</p>
</li>
<li><p>useSelector를 여러 번 호출하여, store의 가능한 가장 작은 state를 return 하라.</p>
</li>
<li><p>성능을 위해 ID로 목록 항목에서 데이터를 선택하라.</p>
</li>
</ul>
<h3 id="ref">Ref</h3>
<p><a href="https://redux.js.org/tutorials/fundamentals/part-1-overview">https://redux.js.org/tutorials/fundamentals/part-1-overview</a></p>
<p><a href="https://redux.js.org/tutorials/fundamentals/part-2-concepts-data-flow#reducers">https://redux.js.org/tutorials/fundamentals/part-2-concepts-data-flow#reducers</a></p>
<p>state, action, reducer <a href="https://redux.js.org/tutorials/fundamentals/part-3-state-actions-reducers">https://redux.js.org/tutorials/fundamentals/part-3-state-actions-reducers</a></p>
<p>store { enhancer , middleware } <a href="https://redux.js.org/tutorials/fundamentals/part-4-store">https://redux.js.org/tutorials/fundamentals/part-4-store</a></p>
<p>ui <a href="https://redux.js.org/tutorials/fundamentals/part-5-ui-react">https://redux.js.org/tutorials/fundamentals/part-5-ui-react</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React Hook]]></title>
            <link>https://velog.io/@ve_hye_ona/React-Hook</link>
            <guid>https://velog.io/@ve_hye_ona/React-Hook</guid>
            <pubDate>Thu, 16 Mar 2023 04:29:21 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>함수 Component에서 React state와 생명주기 기능을 연동(hook into)할 수 있게 해주는 함수</p>
</blockquote>
<p>Hook은 React 버전 16.8부터 새로운 요소로 추가되어, 기존의 React 컨셉을 대체하지 않으면서도 React의 props, state, context, refs, lifecycle 개념에 좀 더 직관적인 API를 제공한다.</p>
<p>기존 React는 Component 간 재사용이 가능한 로직을 붙이는 방법을 제공하지 않는다.
Hook을 통해 기존의 계층의 변화 없이(Class 없이) 상태 관련 로직을 재사용할 수 있게 되어 상태 값 관리가 보다 편리해진다.
그래서 class 내에서는 동작하지 않는다.</p>
<h2 id="hook-규칙">Hook 규칙</h2>
<ol>
<li><strong>최상위에서만 Hook을 호출</strong>해야 한다.
반복문, 조건문, 중첩된 함수 내에서 Hook을 실행하지 말라.</li>
</ol>
<ul>
<li>이를 통해 컴포넌트가 렌더링 될 때마다 항상 동일한 순서로 Hook이 호출되는 것이 보장되면서, useState와 useEffect가 여러 번 호출되는 중에도 Hook의 상태가 올바르게 유지된다.</li>
</ul>
<ol start="2">
<li><strong>React 함수 Component 내에서만 (혹은 Custom Hook에서) Hook을 호출</strong>해야 한다.
일반 JavaScript 함수에서는 Hook을 호출해서는 안 된다.</li>
</ol>
<ul>
<li>이를 통해 컴포넌트의 모든 상태 관련 로직을 소스코드에서 명확하게 보이도록 할 수 있다.</li>
</ul>
<h3 id="eslint-플러그인">ESLint 플러그인</h3>
<p>Hook의 2가지 규칙을 강제하는 플러그인으로 Create React App에 기본적으로 포함되어 있다.</p>
<h4 id="설치-방법">설치 방법</h4>
<pre><code>npm install eslint-plugin-react-hooks --save-dev</code></pre><h2 id="hook-api">Hook API</h2>
<h3 id="state-hook-usestate">State Hook: useState</h3>
<p>state를 함수 Component 안에서 사용할 수 있게 해준다.</p>
<pre><code>const [count, setCount] = useState(0);</code></pre><ul>
<li><p>현재의 <strong>state 값</strong>과 이 값을 <strong>업데이트하는 함수</strong>를 쌍으로 반환한다.</p>
</li>
<li><p>초기 state는 첫 번째 렌더링에서만 사용된다.</p>
</li>
<li><p>state는 Class Component에서와 달리 객체일 필요가 없고, 숫자나 문자 타입을 가질 수 있다.</p>
</li>
</ul>
<h3 id="effect-hook-useeffect">Effect Hook: useEffect</h3>
<p>React Component 안에서 데이터를 가져 오거나 구독하고, DOM을 직접 조작하는 등의 side effects를 수행할 수 있게 한다.</p>
<pre><code> const [count, setCount] = useState(0);

  // componentDidMount, componentDidUpdate와 비슷합니다
  useEffect(() =&gt; {
    // 브라우저 API를 이용해 문서의 타이틀을 업데이트합니다
    document.title = `You clicked ${count} times`;
  });</code></pre><ul>
<li>React DOM을 바꾼 뒤에 useEffect 함수가 실행된다.</li>
</ul>
<h4 id="clean-up을-이용하지-않는-side-effects">Clean-up을 이용하지 않는 Side-effects</h4>
<p>Ex.</p>
<ul>
<li>네트워크 리퀘스트</li>
<li>DOM 수동 조작</li>
<li>로깅</li>
</ul>
<p>아래의 같은 코드를 비교해보자.</p>
<p>i. Class Component</p>
<pre><code>class Example extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  componentDidMount() {
    document.title = `You clicked ${this.state.count} times`;
  }
  componentDidUpdate() {
    document.title = `You clicked ${this.state.count} times`;
  }

  render() {
    return (
      &lt;div&gt;
        &lt;p&gt;You clicked {this.state.count} times&lt;/p&gt;
        &lt;button onClick={() =&gt; this.setState({ count: this.state.count + 1 })}&gt;
          Click me
        &lt;/button&gt;
      &lt;/div&gt;
    );
  }
}</code></pre><p>ii. 함수 Component</p>
<pre><code>import React, { useState, useEffect } from &#39;react&#39;;

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() =&gt; {
    document.title = `You clicked ${count} times`;
  });

  return (
    &lt;div&gt;
      &lt;p&gt;You clicked {count} times&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;
        Click me
      &lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><p>ii.의 경우의 useEffect는 React Component의 모든 렌더링(DOM 업데이트를 수행한; 마운트 + 업데이트) 이후에 수행된다. </p>
<h4 id="clean-up이-필요한-side-effects">Clean-up이 필요한 Side-effects</h4>
<p>Ex. 구독(subscription)을 설정해야 하는 경우에는 메모리 누수가 발생하지 않도록 정리가 필요하다.</p>
<p>i. Class Component</p>
<pre><code>class FriendStatus extends React.Component {
  constructor(props) {
    super(props);
    this.state = { isOnline: null };
    this.handleStatusChange = this.handleStatusChange.bind(this);
  }

  componentDidMount() {
      document.title = `You clicked ${this.state.count} times`;
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }
  componentDidUpdate(prevProps) {
    // 이전 friend.id에서 구독을 해지합니다.
    ChatAPI.unsubscribeFromFriendStatus(
      prevProps.friend.id,
      this.handleStatusChange
    );
    // 다음 friend.id를 구독합니다.
    ChatAPI.subscribeToFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }
  componentWillUnmount() {
    ChatAPI.unsubscribeFromFriendStatus(
      this.props.friend.id,
      this.handleStatusChange
    );
  }
  handleStatusChange(status) {
    this.setState({
      isOnline: status.isOnline
    });
  }

  render() {
    if (this.state.isOnline === null) {
      return &#39;Loading...&#39;;
    }
    return this.state.isOnline ? &#39;Online&#39; : &#39;Offline&#39;;
  }
}</code></pre><p>ii. 함수 Component</p>
<pre><code>function FriendStatusWithCounter(props) {
  const [count, setCount] = useState(0);
  useEffect(() =&gt; {
    document.title = `You clicked ${count} times`;
  });

  const [isOnline, setIsOnline] = useState(null);
  useEffect(() =&gt; {
    function handleStatusChange(status) {
      setIsOnline(status.isOnline);
    }

    ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
    return () =&gt; {
      ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
    };
  });
  // ...
}</code></pre><ul>
<li>i. 과 다르게 ii.에서는 업데이트를 위한 특별한 추가 코드가 필요하지 않다.</li>
</ul>
<h4 id="최적화-불필요한-re-rendering-방지">최적화: 불필요한 re-rendering 방지</h4>
<p>i. Class Component</p>
<pre><code>componentDidUpdate(prevProps, prevState) {
  if (prevState.count !== this.state.count) {
    document.title = `You clicked ${this.state.count} times`;
  }
}</code></pre><p>ii. 함수 Component</p>
<p>** useEffect 두 번째 인자로 배열로써** 전달하면, 배열에 해당하는 값들이 동일하다면 useEffect를 건너뛴다.</p>
<pre><code>useEffect(() =&gt; {
  document.title = `You clicked ${count} times`;
}, [count]); // count가 바뀔 때만 effect를 재실행합니다.</code></pre><h3 id="심화-usereducer">심화: useReducer</h3>
<p>상태를 관리할 때 컴퍼넌트의 상태 업데이트 로직을 컴포넌트에서 분리시킬 수 있다.</p>
<p>i. useState</p>
<pre><code>mport React, { useState } from &#39;react&#39;;

function Counter() {
  const [number, setNumber] = useState(0);

  const onIncrease = () =&gt; {
    setNumber(prevNumber =&gt; prevNumber + 1);
  };

  const onDecrease = () =&gt; {
    setNumber(prevNumber =&gt; prevNumber - 1);
  };

  return (
    &lt;div&gt;
      &lt;h1&gt;{number}&lt;/h1&gt;
      &lt;button onClick={onIncrease}&gt;+1&lt;/button&gt;
      &lt;button onClick={onDecrease}&gt;-1&lt;/button&gt;
    &lt;/div&gt;
  );
}

export default Counter;</code></pre><p>ii. useReducer</p>
<pre><code>import React, { useReducer } from &#39;react&#39;;

function reducer(state, action) {
  switch (action.type) {
    case &#39;INCREMENT&#39;:
      return state + 1;
    case &#39;DECREMENT&#39;:
      return state - 1;
    default:
      return state;
  }
}

function Counter() {
  const [number, dispatch] = useReducer(reducer, 0);

  const onIncrease = () =&gt; {
    dispatch({ type: &#39;INCREMENT&#39; });
  };

  const onDecrease = () =&gt; {
    dispatch({ type: &#39;DECREMENT&#39; });
  };

  return (
    &lt;div&gt;
      &lt;h1&gt;{number}&lt;/h1&gt;
      &lt;button onClick={onIncrease}&gt;+1&lt;/button&gt;
      &lt;button onClick={onDecrease}&gt;-1&lt;/button&gt;
    &lt;/div&gt;
  );
}

export default Counter;</code></pre><h3 id="useref">useRef</h3>
<h4 id="용도">용도</h4>
<ol>
<li><strong>Component 안에서 조회/수정할 수 있는 변수 관리</strong>하는 경우(setTimeout, setInterval을 통해 만들어진 id, 외부 라이브러리를 사용하여 생성된 인스턴스, scroll 위치)에 사용한다.<ul>
<li>useState와 달리 useRef로 관리하는 변수는 값이 바뀐다고 해서 컴포넌트가 <strong>리렌더링되지 않는다.</strong></li>
</ul>
</li>
<li><strong>직접 DOM을 선택해야 하는 경우</strong>(특정 엘리먼트 크기를 가져올 때, 스크롤바 위치를 가져오거나 설정할 때, 포커스를 설정할 때) React에서는 ref를 사용하는데 Hook 함수로는 useRef가 존재한다.</li>
</ol>
<h4 id="사용-방식">사용 방식</h4>
<ol>
<li>useRef()를 이용하여 ref 객체를 만든다.</li>
<li>선택하고 싶은 DOM에 ref 값으로 설정해준다.</li>
<li>그러면 ref 객체의 .current 값이 우리가 원하는 DOM을 가르킨다.</li>
</ol>
<p>Ex1.</p>
<pre><code>import React, { useRef } from &#39;react&#39;;
import UserList from &#39;./UserList&#39;;

function App() {
  const users = [
    {
      id: 1,
      username: &#39;velopert&#39;,
      email: &#39;public.velopert@gmail.com&#39;
    },
    {
      id: 2,
      username: &#39;tester&#39;,
      email: &#39;tester@example.com&#39;
    },
    {
      id: 3,
      username: &#39;liz&#39;,
      email: &#39;liz@example.com&#39;
    }
  ];

  const nextId = useRef(4);
  const onCreate = () =&gt; {
    // 나중에 구현 할 배열에 항목 추가하는 로직
    // ...

    nextId.current += 1;
  };
  return &lt;UserList users={users} /&gt;;
}

export default App;</code></pre><p>Ex2. 초기화 버튼을 누르면 이름 input에 포커스가 잡힘</p>
<pre><code>import React, { useState, useRef } from &#39;react&#39;;

function InputSample() {
  const [inputs, setInputs] = useState({
    name: &#39;&#39;,
    nickname: &#39;&#39;
  });
  const nameInput = useRef();

  const { name, nickname } = inputs; // 비구조화 할당을 통해 값 추출

  const onChange = e =&gt; {
    const { value, name } = e.target; // 우선 e.target 에서 name 과 value 를 추출
    setInputs({
      ...inputs, // 기존의 input 객체를 복사한 뒤
      [name]: value // name 키를 가진 값을 value 로 설정
    });
  };

  const onReset = () =&gt; {
    setInputs({
      name: &#39;&#39;,
      nickname: &#39;&#39;
    });
    nameInput.current.focus();
  };

  return (
    &lt;div&gt;
      &lt;input
        name=&quot;name&quot;
        placeholder=&quot;이름&quot;
        onChange={onChange}
        value={name}
        ref={nameInput}
      /&gt;
      &lt;input
        name=&quot;nickname&quot;
        placeholder=&quot;닉네임&quot;
        onChange={onChange}
        value={nickname}
      /&gt;
      &lt;button onClick={onReset}&gt;초기화&lt;/button&gt;
      &lt;div&gt;
        &lt;b&gt;값: &lt;/b&gt;
        {name} ({nickname})
      &lt;/div&gt;
    &lt;/div&gt;
  );
}

export default InputSample;</code></pre><h3 id="usememo">useMemo</h3>
<p><strong>성능 최적화를 위해 연산된 값을 재사용</strong>할 때 사용한다.</p>
<h4 id="사용-방식-1">사용 방식</h4>
<p>useMemo((값을 어떻게 연산할지 정의하는 함수), (배열));</p>
<h4 id="사용-예시">사용 예시</h4>
<p>다음은 useMemo를 사용하지 않는 것과 사용했을 때의 차이를 보여주는 예시 코드이다.
useMemo를 사용하게 되면 useMemo의 두 번째 인자로 넣은 배열의 내용이 바<strong>뀌면 첫 번째 인자로 등록한 함수를 호출해 값을 연산</strong>하고, <strong>내용이 바뀌지 않았다면 이전에 연산한 값을 재사용</strong>한다.</p>
<pre><code>import React, { useRef, useState } from &#39;react&#39;;
import UserList from &#39;./UserList&#39;;
import CreateUser from &#39;./CreateUser&#39;;

function countActiveUsers(users) {
  console.log(&#39;활성 사용자 수를 세는중...&#39;);
  return users.filter(user =&gt; user.active).length;
}

function App() {
  const [inputs, setInputs] = useState({
    username: &#39;&#39;,
    email: &#39;&#39;
  });
  const { username, email } = inputs;
  const onChange = e =&gt; {
    const { name, value } = e.target;
    setInputs({
      ...inputs,
      [name]: value
    });
  };
  const [users, setUsers] = useState([
    {
      id: 1,
      username: &#39;velopert&#39;,
      email: &#39;public.velopert@gmail.com&#39;,
      active: true
    },
    {
      id: 2,
      username: &#39;tester&#39;,
      email: &#39;tester@example.com&#39;,
      active: false
    },
    {
      id: 3,
      username: &#39;liz&#39;,
      email: &#39;liz@example.com&#39;,
      active: false
    }
  ]);

  const nextId = useRef(4);
  const onCreate = () =&gt; {
    const user = {
      id: nextId.current,
      username,
      email
    };
    setUsers(users.concat(user));

    setInputs({
      username: &#39;&#39;,
      email: &#39;&#39;
    });
    nextId.current += 1;
  };

  const onRemove = id =&gt; {
    // user.id 가 파라미터로 일치하지 않는 원소만 추출해서 새로운 배열을 만듬
    // = user.id 가 id 인 것을 제거함
    setUsers(users.filter(user =&gt; user.id !== id));
  };
  const onToggle = id =&gt; {
    setUsers(
      users.map(user =&gt;
        user.id === id ? { ...user, active: !user.active } : user
      )
    );
  };
  const count = countActiveUsers(users);
  return (
    &lt;&gt;
      &lt;CreateUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      /&gt;
      &lt;UserList users={users} onRemove={onRemove} onToggle={onToggle} /&gt;
      &lt;div&gt;활성사용자 수 : {count}&lt;/div&gt;
    &lt;/&gt;
  );
}

export default App;</code></pre><pre><code>import React, { useRef, useState, useMemo } from &#39;react&#39;;
import UserList from &#39;./UserList&#39;;
import CreateUser from &#39;./CreateUser&#39;;

function countActiveUsers(users) {
  console.log(&#39;활성 사용자 수를 세는중...&#39;);
  return users.filter(user =&gt; user.active).length;
}

function App() {
  const [inputs, setInputs] = useState({
    username: &#39;&#39;,
    email: &#39;&#39;
  });
  const { username, email } = inputs;
  const onChange = e =&gt; {
    const { name, value } = e.target;
    setInputs({
      ...inputs,
      [name]: value
    });
  };
  const [users, setUsers] = useState([
    {
      id: 1,
      username: &#39;velopert&#39;,
      email: &#39;public.velopert@gmail.com&#39;,
      active: true
    },
    {
      id: 2,
      username: &#39;tester&#39;,
      email: &#39;tester@example.com&#39;,
      active: false
    },
    {
      id: 3,
      username: &#39;liz&#39;,
      email: &#39;liz@example.com&#39;,
      active: false
    }
  ]);

  const nextId = useRef(4);
  const onCreate = () =&gt; {
    const user = {
      id: nextId.current,
      username,
      email
    };
    setUsers(users.concat(user));

    setInputs({
      username: &#39;&#39;,
      email: &#39;&#39;
    });
    nextId.current += 1;
  };

  const onRemove = id =&gt; {
    // user.id 가 파라미터로 일치하지 않는 원소만 추출해서 새로운 배열을 만듬
    // = user.id 가 id 인 것을 제거함
    setUsers(users.filter(user =&gt; user.id !== id));
  };
  const onToggle = id =&gt; {
    setUsers(
      users.map(user =&gt;
        user.id === id ? { ...user, active: !user.active } : user
      )
    );
  };
  const count = useMemo(() =&gt; countActiveUsers(users), [users]);
  return (
    &lt;&gt;
      &lt;CreateUser
        username={username}
        email={email}
        onChange={onChange}
        onCreate={onCreate}
      /&gt;
      &lt;UserList users={users} onRemove={onRemove} onToggle={onToggle} /&gt;
      &lt;div&gt;활성사용자 수 : {count}&lt;/div&gt;
    &lt;/&gt;
  );
}

export default App;</code></pre><h3 id="usecallback">useCallback</h3>
<p>특정 함수를 재사용하며 성능 최적화</p>
<h4 id="사용-방식-2">사용 방식</h4>
<p>useCallback((재사용 함수), (함수에 필요한 값들이 포함된 배열));</p>
<h3 id="ref">Ref</h3>
<p><a href="https://ko.reactjs.org/docs/hooks-overview.html">https://ko.reactjs.org/docs/hooks-overview.html</a></p>
<p><a href="https://ko.reactjs.org/docs/hooks-state.html">https://ko.reactjs.org/docs/hooks-state.html</a></p>
<p><a href="https://ko.reactjs.org/docs/hooks-effect.html">https://ko.reactjs.org/docs/hooks-effect.html</a></p>
<p><a href="https://ko.reactjs.org/docs/hooks-rules.html">https://ko.reactjs.org/docs/hooks-rules.html</a></p>
<p><a href="https://ko.reactjs.org/docs/hooks-reference.html#usecontext">https://ko.reactjs.org/docs/hooks-reference.html#usecontext</a></p>
<p><a href="https://react.vlpt.us/basic/10-useRef.html">https://react.vlpt.us/basic/10-useRef.html</a></p>
<p><a href="https://react.vlpt.us/basic/17-useMemo.html">https://react.vlpt.us/basic/17-useMemo.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React.js]]></title>
            <link>https://velog.io/@ve_hye_ona/React.js</link>
            <guid>https://velog.io/@ve_hye_ona/React.js</guid>
            <pubDate>Wed, 15 Mar 2023 06:46:50 GMT</pubDate>
            <description><![CDATA[<p>웹페이지에 인터랙션이 자주 발생하고, 동적인 UI를 기존의 Javascript만으로 표현하면 개발과 수정이 일어날때마다 DOM을 직접 수정해야하기 때문에 코드가 난잡해지는 문제가 발생하곤 한다.</p>
<p>처리해야 할 이벤트도 다양해지고, 관리해야할 상태 값이나 DOM의 구조도 다양해지게 된다면 이에 따라 처리해야하는 업데이트 규칙도 복잡해진다.</p>
<p>리액트는 이러한 문제점을 개선하기 위해 아래와 같은 방법을 사용한다.</p>
<p>View에서 어떠한 상태가 바뀌었을 때 그 상태에 따라 DOM을 어떻게 업데이트 할지를 정하는 것이 아니라, 아예 View를 다 날려버리고 새로 보여주면 코드가 난잡해지는 것을 방지할 수 있지 않을까, 하는 아이디어에서 리엑트가 탄생했다.</p>
<h1 id="spa-single-page-application">SPA (Single Page Application)</h1>
<p>사용자가 한 페이지의 머무르면서 새로운 페이지로 바뀔 때 마다 필요한 정보만 추가적으로 받아와 부분적으로 업데이트한다.</p>
<ul>
<li>첫 화면 로딩 시간이 다소 길다는 점이 있다.</li>
<li>라우팅에 따라 다른 뷰를 보여줄 수 있다.</li>
</ul>
<h1 id="가상-돔virtual-dom">가상 돔(Virtual DOM)</h1>
<p>DOM을 추상화한 가상의 객체로,
브라우저에 실제로 보여지는 DOM이 아니라 단순히 메모리에 가상으로 존재하는 DOM으로서, 단순한 Javascript객체이기 때문에 작동 성능이 브라우저에서 DOM을 보여주는 것보다 속도가 훨씬 빠르다.</p>
<p>일반적인 브라우저 렌더링 과정으로는</p>
<ol>
<li>HTML 파싱 -&gt; DOM 객체 생성 -&gt; CSS 파싱 -&gt; 스타일 규칙 생성</li>
<li>위의 과정을 합쳐 실제로 웹 브라우저에 보여줘야 할 &#39;render tree&#39; 를 만든다.</li>
<li>이 렌더 트리 기준으로 레이아웃을 배치하고 Paint의 작업을 한다.</li>
</ol>
<p>이 과정에서 변경될 구성 요소가 바뀌면 전체가 렌더링이 되는데 매우 비효율적이라고 볼 수 있다.
그래서 리액트를 사용하는 이유 중 하나가 바로 Virtual DOM 이다.
<strong>리액트는 상태가 업데이트 되면 Virtual DOM은 기존 DOM과 변경될 Virtual DOM의 차이를 판단하고 변경된 구성요소만 찾아 그 부분만 렌더링을 한다.</strong></p>
<h1 id="diffing-알고리즘">diffing 알고리즘</h1>
<p>위에 설명한 Virtual DOM과 관련이 크다.
변경된 부분만 감지해서 바뀐 부분만 업데이트 하는 방식을 취하게 되는데 이 변경된 부분을 감지하는 것을 diffing Algorihm 이라고 한다.
일반적인 트리 구조의 비교는 O(n^3)의 시간이 소요된다고 한다. 하지만 리액트는 이러한 diffing 알고리즘으로 인해 O(n)의 시간에 해결하고 있다.</p>
<h1 id="key를-사용하는-이유">key를 사용하는 이유</h1>
<p>이것 또한 Virtual DOM과 diffing 알고리즘과 연관이 있다.
하나의 JSX 태그는 자바스크립트 객체로 구성되는데 이 객체에는 해당 객체가 Virtual DOM의 요소임을 확인해주는 심볼값과 각각의 Virtual DOM를 고유하게 구분하는 key 값이 들어가게 된다.</p>
<p>그래서 map 을 사용했을 때, 해당 리스트에 고유한 key값을 넣어줘야한다. 리액트는 이 key들의 비교를 통해 리스트의 요소가 추가되거나 삭제되었을 때 상태를 빠르게 감지하고 반영할 수 있다.</p>
<p>쉽게 말해 엘리먼트 혹은 컴포넌트의 변화를 감지하기 위함이고 이는 효율적인 DOM 사용으로 귀결된다.</p>
<h1 id="환경세팅">환경세팅</h1>
<h2 id="webpack">Webpack</h2>
<blockquote>
<p>최신 프런트엔드 프레임워크에서 가장 많이 사용되는 모듈 번들러(Module Bundler)</p>
</blockquote>
<h3 id="모듈-번들러">모듈 번들러</h3>
<p>웹 애플리케이션을 구성하는 자원(HTML, CSS, Javscript, Images 등)을 모두 각각의 모듈로 보고 이를 조합해서 병합된 하나의 결과물을 만드는 도구를 의미합니다</p>
<h3 id="사용하는-이유">사용하는 이유</h3>
<ul>
<li>파일 단위의 자바스크립트 모듈 관리의 필요성</li>
<li>웹 개발 작업 자동화 도구</li>
<li>웹 애플리케이션의 빠른 로딩 속도와 높은 성능</li>
</ul>
<h2 id="prettier">Prettier</h2>
<p>협업을 하게 될 때, 일관성 있는 코드 스타일은 정말 중요하다.
그래서 일관성 있는 코드 스타일 규칙만 설정해주면 알아서 자동으로 그 규칙에 맞게 코드들을 정리해준다.</p>
<h2 id="babel">Babel</h2>
<p>최신 문법을 브라우저가 이해할 수 있는 자바스크립트로 통역
브라우저는 JSX를 이해하지 못한다.
그러니 바벨이라는 통역사로 <strong>JSX -&gt; Javascript</strong></p>
<h2 id="eslint">Eslint</h2>
<p>ESLint가 코드 퀄리티를 일관적으로 유지
문법 에러를 잡아주거나 더 좋은 코드 구현 방식을 사용하도록 해준다.</p>
<h3 id="ref">Ref</h3>
<p><a href="https://narup.tistory.com/183">https://narup.tistory.com/183</a></p>
<p><a href="https://velog.io/@leemember/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-%EB%8B%A8%EA%B3%A8-%EA%B0%9C%EB%85%90%EB%93%A4-%EC%A0%95%EB%A6%AC-%EB%A6%AC%EC%95%A1%ED%8A%B8-%ED%8E%B8">https://velog.io/@leemember/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-%EB%8B%A8%EA%B3%A8-%EA%B0%9C%EB%85%90%EB%93%A4-%EC%A0%95%EB%A6%AC-%EB%A6%AC%EC%95%A1%ED%8A%B8-%ED%8E%B8</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Components, props와 State]]></title>
            <link>https://velog.io/@ve_hye_ona/Components-props%EC%99%80-State</link>
            <guid>https://velog.io/@ve_hye_ona/Components-props%EC%99%80-State</guid>
            <pubDate>Tue, 14 Mar 2023 03:06:46 GMT</pubDate>
            <description><![CDATA[<h1 id="components">Components</h1>
<blockquote>
<p>화면을 이루는 &#39;요소&#39;로 여러 곳에서 재사용 가능한 UI 코드 조각</p>
</blockquote>
<p>React를 사용할 때 Component는 class나 function으로 정의할 수 있다.</p>
<ul>
<li><p>Component의 이름은 항상 대문자로 시작한다.</p>
</li>
<li><p>코드의 재사용성과 유지보수성을 증가시켜 준다.</p>
</li>
<li><p><strong>데이터의 단방향성</strong></p>
<ul>
<li>데이터는 아래로 흐른다.</li>
<li>부모 Component는 자식 Component가 어떤 상태인지 알 수 없고 관심을 가지지 않는다.</li>
<li>state가 소유하고 설정한 Component 이외에는 어떠한 Component에서도 접근할 수 없다.</li>
<li><strong>Component가 자신의 state를 자식 Component에 props로 전달할 수 있다</strong>.</li>
</ul>
</li>
</ul>
<h2 id="component와-props">Component와 Props</h2>
<h3 id="props">Props</h3>
<p>속성을 나타내는 데이터로 Property의 준말</p>
<ul>
<li>부모 Component에서 자식 Component로 전달해 준 데이터</li>
</ul>
<p>Props를 개체로 받는 Component의 예시는 다음과 같다.</p>
<p>Ex. Class Component</p>
<pre><code>import React from &#39;react&#39;
class Welcome extends React.Component {
  render() {
    return &lt;h1&gt;Hello, {this.props.name}&lt;/h1&gt;;
  }
}</code></pre><p>Ex. Function Component</p>
<pre><code>function Welcome(props) {
  return &lt;h1&gt;Hello, {props.name}&lt;/h1&gt;;
}</code></pre><h4 id="props는-읽기-전용이다">props는 읽기 전용이다.</h4>
<p>따라서 Component에서 자체 props를 수정할 수 없다.
즉, 모든 React Component는 자신의 props를 다룰 때 반드시 자신의 입력값을 바꾸지 않는 순수 함수처럼 동작해야 한다.</p>
<h2 id="component-rendering">Component Rendering</h2>
<p>React Element는 DOM 태그와 사용자 정의 Component 모두로 나타낼 수 있다.
React가 사용자 정의 Component로 작성한 Element를 발견하면 <strong>JSX 속성과 자식을 해당 Component에 단일 객체로 전달</strong>하는데, 이를 <strong>Props</strong>라 한다.</p>
<p>Ex.</p>
<pre><code>const element = &lt;Welcome name=&quot;Sara&quot; /&gt;;</code></pre><h2 id="component-합성--추출">Component 합성 / 추출</h2>
<p>Component는 자신의 출력에 다른 Component를 참조할 수 있다.</p>
<p>Ex.</p>
<pre><code>function Welcome(props) {
  return &lt;h1&gt;Hello, {props.name}&lt;/h1&gt;;
}

function App() {
  return (
    &lt;div&gt;
      &lt;Welcome name=&quot;Sara&quot; /&gt;
      &lt;Welcome name=&quot;Cahal&quot; /&gt;
      &lt;Welcome name=&quot;Edite&quot; /&gt;
    &lt;/div&gt;
  );
}</code></pre><p>또한 Component를 여러 개의 작은 Component로 나눌 수 있다.</p>
<h2 id="state">State</h2>
<p>한 Component 내에서 완전히 제어되는 상태 (local/캡슐화) 를 나타내고 동적인 데이터를 다룰 때 사용</p>
<ul>
<li><p>constructor가 아니라면 직접 State를 수정하지 않고 대신 <strong>setState()</strong>를 사용한다.
직접 state를 수정하는 경우, component가 다시 렌더링되지 않는다.</p>
<pre><code>  // Wrong
  this.state.comment = &#39;Hello&#39;;
  // Correct
  this.setState({comment: &#39;Hello&#39;});</code></pre></li>
<li><p>state 업데이트는 비동기적일 수 있으므로 객체보다는 함수를 인자로 사용하는 형태의 setState()를 사용하자.</p>
<pre><code>  // Wrong
  this.setState({
        counter: this.state.counter +     this.props.increment,
  });
  // Correct
  this.setState((state, props) =&gt; ({
        counter: state.counter + props.increment
  }));</code></pre></li>
<li><p>state 업데이트는 병합된다. 즉, setState()를 호출할 때, React는 제공한 객체를 현재 state로 병합한다. 따라서 여러 번의 setState() 호출로 여러 변수를 독립적으로 업데이트할 수 있다.</p>
</li>
</ul>
<p>-** Hook의 useState**로 상태를 추가해줄 수도 있다.</p>
<h2 id="생명-주기와-생명-주기-메서드">생명 주기와 생명 주기 메서드</h2>
<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/81b1c808-ead1-4e27-9e62-11baddf6cb7a/image.png" alt=""></p>
<h3 id="mount">Mount</h3>
<p>Component의 instance가 생성되어 DOM 상에 삽입될 때 다음 메서드들이 순서대로 호출된다.</p>
<ol>
<li>constructor()<ul>
<li>instance에 이벤트 처리 <strong>메서드를 바인딩</strong>하거나 <strong>state를 초기화</strong>하는 작업이 없다면, 해당 React Component에서는 constructor를 구현하지 않아도 된다.</li>
<li>구현하는 경우, props를 기본 constructor로 호출해야 한다.</li>
<li><strong>constructor() 내부에서 setState()를 호출하면 안된다</strong>. component에 지역 state가 필요하다면 constructor 내에서 <strong>this.state에 초기 state 값을 할당</strong>하면 된다. 다만 여기서도 state에 props를 복사하면 안 된다.<pre><code>constructor(props) {
    super(props);
    // 여기서 this.setState()를 호출하면 안 됩니다!
    this.state = { counter: 0 };
    this.handleClick = this.handleClick.bind(this);
}</code></pre></li>
</ul>
</li>
<li>static getDerivedStateFromProps()</li>
<li>render()<ul>
<li>Class component 내에서 반드시 구현되어야 하는 유일한 메서드</li>
<li><strong>component의 state를 변경하지 않고, 호출될 때마다 동일한 결과를 반환해야하며, 브라우저와 직접적으로 상호작용하지 않는다.</strong></li>
</ul>
</li>
<li>componentDidMount()<ul>
<li>component가 mount된 직후 (트리에 삽입된 직후)에 호출</li>
<li>브라우저와 상호작용하는 작업이 필요할 때 사용</li>
</ul>
</li>
</ol>
<h3 id="업데이트">업데이트</h3>
<p>props나 state가 변경되면 업데이트가 발생한다.
이 때 component가 다시 렌더링되면서 다음 메서드들이 순서대로 호출된다.</p>
<ol>
<li>static getDerivedStateFromProps()</li>
<li>shouldComponentUpdate()</li>
<li>render()</li>
<li>getSnapshotBeforeUpdate()</li>
<li>componentDidUpdate()</li>
</ol>
<h3 id="unmount">Unmount</h3>
<p>component가 DOM 상에서 제거될 때 호출된다.</p>
<ul>
<li>componentWillUnmount()</li>
</ul>
<h3 id="오류-처리">오류 처리</h3>
<p>자식 컴포넌트를 렌더링하거나, 자식 컴포넌트가 생명주기 메서드를 호출하거나, 또는 자식 컴포넌트가 생성자 메서드를 호출하는 과정에서 오류가 발생했을 때 호출된다.</p>
<ul>
<li>static getDerivedStateFromError()</li>
<li>componentDidCatch()</li>
</ul>
<h3 id="state와-생명주기-사용-예시">State와 생명주기 사용 예시</h3>
<pre><code>class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () =&gt; this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      &lt;div&gt;
        &lt;h1&gt;Hello, world!&lt;/h1&gt;
        &lt;h2&gt;It is {this.state.date.toLocaleTimeString()}.&lt;/h2&gt;
      &lt;/div&gt;
    );
  }
}

const root = ReactDOM.createRoot(document.getElementById(&#39;root&#39;));
root.render(&lt;Clock /&gt;);</code></pre><h3 id="ref">Ref</h3>
<p><a href="https://ko.reactjs.org/docs/react-component.html">https://ko.reactjs.org/docs/react-component.html</a></p>
<p><a href="https://ko.reactjs.org/docs/components-and-props.html">https://ko.reactjs.org/docs/components-and-props.html</a></p>
<p><a href="https://ko.reactjs.org/docs/state-and-lifecycle.html">https://ko.reactjs.org/docs/state-and-lifecycle.html</a></p>
<p><a href="https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/">https://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Element Rendering]]></title>
            <link>https://velog.io/@ve_hye_ona/Element-Rendering</link>
            <guid>https://velog.io/@ve_hye_ona/Element-Rendering</guid>
            <pubDate>Sun, 12 Mar 2023 11:41:15 GMT</pubDate>
            <description><![CDATA[<h1 id="element">Element</h1>
<p>React 앱의 가장 작은 단위로, 화면에 표시할 내용을 기술한다.</p>
<h1 id="element-rendering">Element Rendering</h1>
<h2 id="dom에-element-렌더링하기">DOM에 element 렌더링하기</h2>
<p>브라우저의 DOM element와 달리 React element는 일반 객체이며 쉽게 생성할 수 있다.
<strong>React DOM은 React element와 일치하도록 매번 DOM을 업데이트</strong>한다.</p>
<p>React 프로젝트를 생성하면 html 파일 중 다음의 코드가 존재한다.</p>
<pre><code>&lt;div id=&quot;root&quot;&gt;&lt;/div&gt;</code></pre><p>위의 코드는 <strong>root DOM 노드</strong>로, 해당 노드 안에 들어가 있는 모든 element들은 <strong>React DOM에서 관리</strong>한다.
React로 구현된 애플리케이션은 일반적으로 하나의 root DOM 노드가 존재하는데, 경우에 따라 여러 독립된 root DOM 노드가 존재할 수 있다.</p>
<p>React element를 렌더링하기 위해서는 다음의 코드와 같이,
DOM element를 ReactDOM.createRoot()에 전달한 다음, React element를 root.render()에 전달해야 한다.</p>
<pre><code>const root = ReactDOM.createRoot(
  document.getElementById(&#39;root&#39;)
);
const element = &lt;h1&gt;Hello, world&lt;/h1&gt;;
root.render(element);</code></pre><h2 id="렌더링된-element-업데이트하기">렌더링된 element 업데이트하기</h2>
<p>React element는 특정 시점의 UI를 보여주는 불변 객체이기 때문에,
element를 생성한 이후에는 해당 element의 children이아 attribute를 변경할 수 없다.</p>
<p>따라서 UI를 업데이트하는 유일한 방법은 <strong>새로운 element를 생성하고 이를 root.render()로 전달</strong>하는 것이다.</p>
<h2 id="변경된-부분만-업데이트하기">변경된 부분만 업데이트하기</h2>
<p><strong>React DOM은 해당 element와 그 자식 element를 이전의 element와 비교하고</strong> DOM을 원하는 상태로 만드는데 <strong>필요한 경우에만 DOM을 업데이트</strong>한다.</p>
<h3 id="ref">Ref</h3>
<p><a href="https://ko.reactjs.org/docs/rendering-elements.html">https://ko.reactjs.org/docs/rendering-elements.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JSX]]></title>
            <link>https://velog.io/@ve_hye_ona/JSX</link>
            <guid>https://velog.io/@ve_hye_ona/JSX</guid>
            <pubDate>Sun, 12 Mar 2023 11:20:35 GMT</pubDate>
            <description><![CDATA[<h1 id="jsx">JSX</h1>
<p>JavaScript를 확장한 문법으로, 
렌더링 로직을 UI 로직(이벤트가 처리되는 방식, 시간에 따라 state가 변하는 방식, 화면에 표시하기 위해 데이터가 준비되는 방식 등)과 연결하기 위해 React와 함께 사용할 것을 권장하며,
<strong>React의 element를 생성</strong>하는 역할을 한다.</p>
<h2 id="jsx과-표현식">JSX과 표현식</h2>
<h3 id="jsx에-표현식-포함하기">JSX에 표현식 포함하기</h3>
<p>JSX의 중괄호 안에는 유효한 모든 Javascript 표현식을 넣을 수 있다.</p>
<pre><code>const name = &#39;Josh Perez&#39;;
const element = &lt;h1&gt;Hello, {name}&lt;/h1&gt;;</code></pre><h3 id="jsx도-표현식이다">JSX도 표현식이다</h3>
<p>컴파일이 끝나면, JSX 표현식이 정규 Javascript 함수 호출이 되고 JavaScript 객체로 인식된다.</p>
<p>따라서 JSX를 if 구문이나 for loop 안에 사용하거나, 변수에 할당하거나, 인자로서 받아들이거나, 함수로부터 반환할 수 있다.</p>
<h2 id="jsx는-주입-공격을-방지한다">JSX는 주입 공격을 방지한다</h2>
<p>React DOM은 JSX에 삽입된 모든 값을 렌더링하기 전에 Escape하므로, 애플리케이션에서 명시적으로 작성되지 않은 내용은 주입되지 않는다.
따라서 XSS(cross-site-scripting) 공격을 방지한다.</p>
<h2 id="jsx는-객체를-표현한다">JSX는 객체를 표현한다</h2>
<p>Babel은 JSX를 React.createElement() 호출로 컴파일한다.
다음 두 예시는 동일하다.</p>
<pre><code>const element = (
  &lt;h1 className=&quot;greeting&quot;&gt;
    Hello, world!
  &lt;/h1&gt;
);</code></pre><pre><code>const element = React.createElement(
  &#39;h1&#39;,
  {className: &#39;greeting&#39;},
  &#39;Hello, world!&#39;
);</code></pre><h3 id="ref">Ref</h3>
<p><a href="https://ko.reactjs.org/docs/introducing-jsx.html">https://ko.reactjs.org/docs/introducing-jsx.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS/TS] JavaScript VS TypeScript]]></title>
            <link>https://velog.io/@ve_hye_ona/JavaScript-VS-TypeScript</link>
            <guid>https://velog.io/@ve_hye_ona/JavaScript-VS-TypeScript</guid>
            <pubDate>Wed, 28 Dec 2022 02:19:36 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/f67a41a0-28be-49b8-b453-28be2a0a6929/image.png" alt=""></p>
<h2 id="javascript">JavaScript</h2>
<p>웹 개발 주요 언어로 웹 페이지를 대화식으로 만드는 프로그래밍 언어</p>
<ul>
<li><p>ES6 Syntax를 따름</p>
</li>
<li><p>클라이언트 측 스크립트 언어</p>
<ul>
<li>사용자가 웹 브라우저를 열고 웹페이지를 요청할 시 해당 요청이 웹 서버로 이동</li>
</ul>
</li>
<li><p>폼 유효성 검사, 애니메이션 적용 및 이벤트 생성 수행</p>
</li>
<li><p>멀티 스레딩, 멀티 프로세싱 기능이 없음</p>
</li>
</ul>
<h2 id="typescript">TypeScript</h2>
<p>Javascript 기반의 언어로 JS의 모든 기능이 있음</p>
<ul>
<li><p>객체 지향 컴파일 &amp; 프로그래밍 언어</p>
<ul>
<li>클래스 기반 객체를 만들 수 있고, class 기반 상속, 캡슐화, 생성자 지원</li>
</ul>
</li>
<li><p>정적 유형 검사 제공</p>
</li>
<li><p>TypeScript 컴파일러를 사용해 .ts 파일을 .js로 변환 및 통합</p>
</li>
<li><p>type</p>
<ul>
<li>var, let</li>
<li>type 정의 시 소문자, 대문자 구별해야 함</li>
<li>type 선언 생략 시 동적 타입 결정 (타입 추론)</li>
<li>타입 선언 생략 + 값 할당 X -&gt; any</li>
</ul>
</li>
</ul>
<br>
<br>


<h3 id="ref">Ref</h3>
<p>JS 참조 블로그</p>
<ul>
<li><a href="https://doozi0316.tistory.com/entry/JavaScript-ECMAScript%EB%9E%80-ES5%EC%99%80-ES6%EC%9D%98-%EC%B0%A8%EC%9D%B4var-const-let-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98-class">https://doozi0316.tistory.com/entry/JavaScript-ECMAScript%EB%9E%80-ES5%EC%99%80-ES6%EC%9D%98-%EC%B0%A8%EC%9D%B4var-const-let-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98-class</a></li>
<li><a href="https://hanamon.kr/javascript-es6-%EB%AC%B8%EB%B2%95/">https://hanamon.kr/javascript-es6-%EB%AC%B8%EB%B2%95/</a></li>
</ul>
<p>TS
<a href="https://joshua1988.github.io/ts/why-ts.html#%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%9E%80">https://joshua1988.github.io/ts/why-ts.html#%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%9E%80</a></p>
<p>var / let / const 차이
<a href="https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-var-let-const-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EB%B3%80%EC%88%98-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85">https://inpa.tistory.com/entry/JS-%F0%9F%93%9A-var-let-const-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EB%B3%80%EC%88%98-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring REST API로 CRUD 구현하기]]></title>
            <link>https://velog.io/@ve_hye_ona/Spring-REST-API%EB%A1%9C-CRUD-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ve_hye_ona/Spring-REST-API%EB%A1%9C-CRUD-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 22 Dec 2022 06:27:12 GMT</pubDate>
            <description><![CDATA[<h1 id="spring-rest-api">Spring Rest API</h1>
<p>Spring 3.0의 @ResponseBody, 그리고 4.0부터 지원되는 <strong>@RestController</strong>를 통해 Rest API 메소드를 지원할 수 있게 되었다.</p>
<ul>
<li><p>@ResponseBody : html을 JSON 형태로 보여주는 역할</p>
<ul>
<li>Method 앞에 사용하는 annotation</li>
</ul>
</li>
<li><p>@RestController = @ResponseBody + @Controller</p>
<ul>
<li>Class 앞에 사용하는 annotation</li>
<li>해당 Class 내의 모든 Method는 자동으로 @ResponseBody가 적용됨</li>
</ul>
</li>
</ul>
<p>Spring에서는 class나 method 앞에 간단한 annotation(@~)을 통해 각 class나 method가 어떤 역할을 해주는지 자동으로 정해준다.</p>
<p>마찬가지로 REST Controller에 대해서도 Annotation을 활용할 수 있는데 그 방법은 크게 두 가지가 있다.</p>
<p>I. 필요한 Controller Class 앞에 @RestController를 붙여주거나,</p>
<p>II. 필요한 Controller Class 앞에 @Controller를 붙여주고, 해당 Class 내의 필요한 Method 앞에는 @RequestBody를 붙여줄 수 있다.</p>
<h2 id="crud와-rest-api">CRUD와 REST API</h2>
<blockquote>
<p><strong>CRUD</strong>
= <strong>C</strong>reate + <strong>R</strong>ead + <strong>U</strong>pdate + <strong>D</strong>elete</p>
</blockquote>
<ol>
<li><p>Read</p>
<ul>
<li>@GetMapping(&quot;/api/~&quot;)</li>
</ul>
</li>
<li><p>Create</p>
<ul>
<li>@PostMapping(&quot;/api/~&quot;)</li>
</ul>
</li>
<li><p>Update</p>
<ul>
<li><p>@PutMapping(&quot;/api/~&quot;)
  : 자원의 전체 교체</p>
</li>
<li><p>@PatchMapping(&quot;/api/~&quot;)
  : 자원의 부분 교체</p>
<pre><code>  - Spring 3.2부터 지원</code></pre></li>
</ul>
</li>
<li><p>Delete</p>
<ul>
<li>@DeleteMapping(&quot;/api/~&quot;)</li>
</ul>
</li>
<li><p>1~4의 다른 방식</p>
<ul>
<li>@RequestMapping(value = &quot;/api/~&quot;, method = RequestMethod.GET/POST... )</li>
</ul>
</li>
</ol>
<h2 id="endpoint-설정">Endpoint 설정</h2>
<p>위의 annotation 예시에서 공통적인 (&quot;/api/~&quot;) 부분은 서버 상 해당 주소에 REST EndPoint를 만들어 준다.</p>
<pre><code>-  (server baseURL)/api/~</code></pre><h2 id="pathvariable">PathVariable</h2>
<p>만약 Endpoint 설정에 있어 그 주소를 다음과 같이 주게 되면 URI 경로의 일부를 parameter로 사용하는 PathVariable을 설정할 수 있다.</p>
<pre><code>@RequestMapping(&quot;/api/{id}&quot;)
public String ex(@PathVariable String id) {
    ...
}</code></pre><h2 id="query-parameter">Query Parameter</h2>
<p>Query parameter를 주고 싶다면 다음과 같이 method를 작성할 수 있다.</p>
<pre><code>@RequestMapping(&quot;/api/~&quot;)
public String ex(@RequestParam(required=false) String id) {
    ...
}</code></pre><ul>
<li>required에 대한 default 설정 값은 true이다.</li>
</ul>
<h2 id="requestbody">RequestBody</h2>
<p>JSON 데이터를 원하는 타입의 객체(여기서는 HashMap으로 변환해야 하는 경우 사용할 수 있다.</p>
<p>즉, @RequestBody는 HTTP 요청의 body를 Java 객체로 받을 수 있게 해준다.</p>
<pre><code>@RequestMapping(&quot;/api/~&quot;)
public String ex(@RequestBody(required=false) HashMap&lt;String, Object&gt; data) {
    ...
}</code></pre><ul>
<li>required에 대한 default 설정 값은 true이다.</li>
</ul>
<ul>
<li>간혹 구글링을 하다보면 @RequestBody는 @GetMapping과 함께 사용하지 못한다고 나와 있는 경우가 많은데, 이와 상관없이 Get, Post 등 모든 REST API와 사용 가능하다.</li>
<li>다만 client 측에서 request body를 전달할 수 없는 경우가 있기 때문에 RequestParameter로 대체하는 것으로 결정하는 경우가 많다.</li>
</ul>
<br>

<h3 id="ref">Ref</h3>
<p><a href="https://rebeccacho.gitbooks.io/spring-study-group/content/chapter16.html">https://rebeccacho.gitbooks.io/spring-study-group/content/chapter16.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CSS Architecture] BEM]]></title>
            <link>https://velog.io/@ve_hye_ona/CSS-Architecture-BEM</link>
            <guid>https://velog.io/@ve_hye_ona/CSS-Architecture-BEM</guid>
            <pubDate>Mon, 19 Dec 2022 16:06:32 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>표준 CSS 방법론
; CSS 클래스명을 어떻게 지으면 좋을지에 대해 정의</p>
</blockquote>
<h1 id="기본-구조">기본 구조</h1>
<p>Block + Element + Modifier</p>
<ul>
<li><p><strong>.(block 명)__(element 명)--(modifier 명)</strong></p>
</li>
<li><p>ID를 사용하지 않음</p>
</li>
<li><p>Class만을 사용함</p>
</li>
<li><p>명명은 &#39;어떻게 보이는가&#39;가 아니라 &#39;어떤 목적이냐&#39;에 따라</p>
</li>
<li><p>명명 시, white space 구분은 &#39;-&#39; 하나로</p>
</li>
</ul>
<h2 id="block">Block</h2>
<p>재사용 가능한 기능적으로** 독립적**인 페이지 component</p>
<p>Ex. </p>
<pre><code>&lt;div class=&quot;logo&quot;&gt;</code></pre><ul>
<li>Nested Block 허용
  Ex. .(block1)&gt;.(block2)
  // block이 block을 감싼 형태 </li>
</ul>
<h2 id="element">Element</h2>
<p>Block을 구성하는 단위</p>
<ul>
<li>자신이 속한 Block 내에서만 의미를 가짐 (<strong>의존적</strong>)</li>
</ul>
<p>Ex. (속한 block 명)__(element 명)</p>
<pre><code>&lt;form class=&quot;search-form&quot;&gt;
    &lt;input class=&quot;search-form__input&quot;/&gt;
    &lt;button class=&quot;search-form__button&quot;&gt;Search&lt;/button&gt;
&lt;/form&gt;</code></pre><ul>
<li><p>Nested Element 허용
  Ex. .block&gt;.block______element1&gt;.block__element2
  // block 내에 element1과 element2가 위치함</p>
</li>
<li><p>class 명에 cascading을 여러 번 표시할 필요가 없음</p>
</li>
</ul>
<p>Ex. </p>
<pre><code>&lt;form class=&quot;search-form&quot;&gt;
  &lt;div class=&quot;search-form__content&quot;&gt;
      &lt;input class=&quot;search-form__input&quot;/&gt;
      &lt;button class=&quot;search-form__button&quot;&gt;Search&lt;/button&gt;
  &lt;/div&gt;
&lt;/form&gt;</code></pre><p>Cf.</p>
<pre><code>&lt;form class=&quot;search-form&quot;&gt;
  &lt;div class=&quot;search-form__content&quot;&gt;
      &lt;input class=&quot;search-form__content__input&quot;/&gt;
      &lt;button class=&quot;search-form__content__button&quot;&gt;Search&lt;/button&gt;
  &lt;/div&gt;
&lt;/form&gt;</code></pre><h2 id="modifier">Modifier</h2>
<p>Block이나 Element의 속성</p>
<p>Ex. (속한 block/element 명)--(modifier 명)</p>
<ol>
<li><p>boolean type 
 Ex. --focused</p>
<pre><code> &lt;ul class=&quot;tab&quot;&gt;
 &lt;li class=&quot;tab__item tab__item--focused&quot;&gt;탭 01&lt;/li&gt;
 &lt;li class=&quot;tab__item&quot;&gt;탭 02&lt;/li&gt;
 &lt;li class=&quot;tab__item&quot;&gt;탭 03&lt;/li&gt;
 &lt;/ul&gt;</code></pre></li>
<li><p>key-value type
 Ex. --theme-normal, --color-gray</p>
<pre><code> &lt;div class=&quot;column&quot;&gt;
 &lt;strong class=&quot;title&quot;&gt;일반 로그인&lt;/strong&gt;
 &lt;form class=&quot;form-login form-login--theme-normal&quot;&gt;
 &lt;input type=&quot;text&quot; class=&quot;form-login__id&quot;/&gt;
 &lt;input type=&quot;password&quot; class=&quot;form-login__password&quot;/&gt;
 &lt;/form&gt;
 &lt;/div&gt;

 &lt;div class=&quot;column&quot;&gt;
 &lt;strong class=&quot;title title--color-gray&quot;&gt;VIP 로그인 (준비중)&lt;/strong&gt;
 &lt;form class=&quot;form-login form-login--theme-special form-login--disabled&quot;&gt;
   &lt;input type=&quot;text&quot; class=&quot;form-login__id&quot;/&gt;
   &lt;input type=&quot;password&quot; class=&quot;form-login__password&quot;/&gt;
   &lt;/form&gt;
   &lt;/div&gt;



</code></pre></li>
</ol>
<h2 id="장점">장점</h2>
<p>클래스 명만으로 마크업 구조를 알기 쉬움</p>
<br>


<h3 id="ref">Ref</h3>
<p>BEM을 따른 마크업 Implementation
<a href="https://nykim.work/15">https://nykim.work/15</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MVC Pattern]]></title>
            <link>https://velog.io/@ve_hye_ona/MVC-Pattern</link>
            <guid>https://velog.io/@ve_hye_ona/MVC-Pattern</guid>
            <pubDate>Mon, 19 Dec 2022 08:17:35 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/ff4d6983-5cd6-4d2c-b31c-40bf4b70bd1d/image.png" alt=""></p>
<blockquote>
<p>Application을 Model-View-Controller의 세 가지 역할로 구분한 개발 방법론 / 소프트웨어 디자인 패턴 </p>
</blockquote>
<blockquote>
<p><strong>Design Pattern</strong>
프로그램 등 개발 중에 발생했던 문제점들에 대해 상황에 따라 간편하게 적용해서 특정한 규약으로 쉽게 쓸 수 있는 형태로 정리한 것으로 유지 보수성을 높임
Ex. MVC 패턴, Strategy 패턴, Observer 패턴 등</p>
</blockquote>
<h1 id="필요성">필요성</h1>
<p>각 component를 분리하여 각자의 역할에 집중할 수 있게끔함으로써 유지보수성, application의 확장성, 유연성이 증가하고, 중복 코딩의 문제점이 사라짐</p>
<h1 id="구조">구조</h1>
<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/72b9366f-5f94-4019-b929-65b71c0b929d/image.png" alt=""></p>
<h2 id="model">Model</h2>
<p><strong>데이터와 비즈니스 로직</strong>을 관리하는 객체</p>
<ul>
<li><p>데이터 : 내부의 상태에 대한 정보나 모델을 표현하는 이름 속성으로 DB, 상수, 초기화 값, 변수 등을 뜻함</p>
</li>
<li><p>모델 상태 변화 시, controller와 view에 통보하면 view는 최신의 결과를 보여주고, controller는 모델의 변화에 따른 적용 가능한 명령을 추가, 제거, 수정할 수 있음</p>
</li>
</ul>
<h4 id="규칙">규칙</h4>
<ol>
<li>사용자가 편집하길 원하는 모든 데이터를 가지고 있어야 한다.</li>
<li>view나 controller에 대해서 어떠한 정보도 알지 말아야 한다.</li>
<li>변경이 일어나면 변경 통지에 대한 처리 방법을 구현해야만 한다.</li>
</ol>
<h2 id="view">View</h2>
<p>사용자 interface 요소</p>
<ul>
<li>데이터 및 객체의 입력 및 출력을 담당; 레이아웃과 화면을 처리함</li>
</ul>
<h4 id="규칙-1">규칙</h4>
<ol>
<li>model이 가지고 있는 정보를 따로 저장해서는 안된다.</li>
<li>model이나 controller와 같이 다른 구성요소들을 몰라야 된다.</li>
<li>변경이 일어나면 변경통지에 대한 처리 방법을 구현해야만 한다.</li>
</ol>
<h2 id="controller">Controller</h2>
<p>명령을 model과 view로 라우팅함
; 사용자가 데이터를 클릭하고 수정하는 것에 대한 이벤트들을 처리하는 부분
; model과 view를 연결해주는 역할</p>
<h4 id="규칙-2">규칙</h4>
<ol>
<li><strong>model이나 view에 대해서 알고 있어야</strong> 한다.</li>
<li>model이나 view의 변경을 모니터링해야 한다.</li>
</ol>
<br>

<h1 id="예시-프레임워크--라이브러리">예시 프레임워크 / 라이브러리</h1>
<p>React, Angular JS, Python Django</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[OOP와 SOLID]]></title>
            <link>https://velog.io/@ve_hye_ona/OOP%EC%99%80-SOLID</link>
            <guid>https://velog.io/@ve_hye_ona/OOP%EC%99%80-SOLID</guid>
            <pubDate>Mon, 19 Dec 2022 07:53:43 GMT</pubDate>
            <description><![CDATA[<h1 id="객체-지향-프로그래밍-oop">객체 지향 프로그래밍 (OOP)</h1>
<blockquote>
<p>컴퓨터 프로그래밍의 패러다임으로써 <del>프로그램을 명령어의 목록으로 보는 시각에서 벗어나</del> 여러 개의 독립된 단위인 객체들의 모임으로 파악하고자하는 것</p>
</blockquote>
<ul>
<li>추상화, 상속, <strong>다형성</strong>, 다중 상속 등을 통해 프로그램을 유연하고 변경이 용이하게 만듦
EX. 역할은 interface로 구현은 이를 구현한 class/객체로 하여 역할과 구현을 분리한다.</li>
</ul>
<h2 id="solid--좋은-객체-지향-설계의-5가지-원칙">SOLID : 좋은 객체 지향 설계의 5가지 원칙</h2>
<ol>
<li><p><strong>Single Responsibility Principle (SRP)</strong> : 단일 책임 원칙</p>
<ul>
<li>하나의 클래스는 하나의 책임만 가진다.</li>
</ul>
</li>
<li><p><strong>Open / Closed Principle (OCP)</strong> : 개방 / 폐쇄 원칙</p>
<ul>
<li><p>확장에는 열려 있으나 변경에는 닫혀 있어야 한다.</p>
</li>
<li><p>cf. 기능을 추가하고자 다형성을 이용하여 클라이언트 코드를 변경하는 경우</p>
</li>
</ul>
</li>
</ol>
<ol start="3">
<li><p><strong>Liskov Substitution Principle (LSP)</strong> : 리스코프 치환 원칙</p>
<ul>
<li><p>프로그램의 객체는 정확성을 깨뜨리지 않으면서 하위 타입의 instance로 바꿀 수 있어야 한다.</p>
</li>
<li><p>EX. 다형성에서 sub-class는 interface 규약을 모두 지켜야 함</p>
</li>
</ul>
</li>
<li><p><strong>Interface Segregation Principle (ISP)</strong> : 인터페이스 분리 원칙</p>
<ul>
<li>특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.</li>
</ul>
</li>
<li><p><strong>Dependency Inversion Principle (DIP)</strong> : 의존관계 역전 원칙</p>
<ul>
<li><p>프로그래머는 추상화에 의존해야지, 구체화에 의존하면 안된다.</p>
</li>
<li><p>변경되기 쉬운 부분(ex. impl)이 아니라 interface와 같은 변경되기 쉽지 않은 것에 의존하도록</p>
</li>
<li><p>Ex. 구현 클래스가 아닌 인터페이스에 의존해야 함</p>
</li>
</ul>
</li>
</ol>
<br>


<h3 id="ref">Ref</h3>
<p>SOLID와 코드 예시
<a href="https://ios-development.tistory.com/705?category=1008271">https://ios-development.tistory.com/705?category=1008271</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Clean Architecture]]></title>
            <link>https://velog.io/@ve_hye_ona/Clean-Architecture</link>
            <guid>https://velog.io/@ve_hye_ona/Clean-Architecture</guid>
            <pubDate>Mon, 19 Dec 2022 07:48:46 GMT</pubDate>
            <description><![CDATA[<h1 id="system-architecture">System Architecture</h1>
<blockquote>
<p>시스템의 구조(structure), 행위(behavior), 뷰(view)를 정의하는 개념 모델로, 각 컴포넌트가 어떻게 상호작용하고 정보를 교환하는지 설명한다.</p>
</blockquote>
<h3 id="목적">목적</h3>
<p>소프트웨어를 계층으로 나눔으로써 관심사를 분리할 수 있다.</p>
<p>이 때, 계층간 경계를 두어 각 Layer를 분리하고, 관심사를 분리하는데 설명한 방식이 Dependency Rule이다.</p>
<blockquote>
<p><strong>Dependency rule</strong>
Software를 이루는 서로 다른 영역을 circular diagram으로 나타내었을 때, higher level일 수록 더 안쪽 circle이 되는 형태를 띤다. (outer circle : mechanism, inner circle : policy)
이 때, <strong>inner circle은 outer circle에 independent</strong>하기 때문에, outer circle의 변화는 inner circle에 영향을 주지 않는다. 반면, inner circle의 변화는 outer circle에 영향을 줄 수 있다.</p>
</blockquote>
<h3 id="중요성">중요성</h3>
<p>이를 통해 다음과 같은 시스템을 생성할 수 있다.</p>
<ol>
<li><p>Framework-independent한 시스템을 구축할 수 있다.</p>
<ul>
<li>System Architecture는 라이브러리 존재 여부나 프레임워크에 한정적이지 않아 도구로써 사용하는 것이 가능하다.</li>
</ul>
</li>
<li><p>테스트가 용이하다.</p>
<ul>
<li>Dependency rule을 따름으로써 Business rule이 UI, DB, 웹 서버 등 외부적인 요인들에 영향 받지 않고 테스트될 수 있다.</li>
</ul>
</li>
<li><p>UI에 독립적이다.</p>
<ul>
<li>시스템의 다른 부분을 고려하지 않고 UI를 변경할 수 있다.</li>
</ul>
</li>
<li><p>Db에 독립적이다.</p>
<ul>
<li>DB (SQL, MongoDB, CouchDB 등)에 독립적으로 변경될 수 있고, Business rule에 얽매이지 않는다.</li>
</ul>
</li>
<li><p>외부 기능에 독립적이다.</p>
<ul>
<li>Business rule은 외부 상황 (DB, UI)에 대해 아무것도 모른다.</li>
</ul>
</li>
</ol>
<blockquote>
<p><strong>Business Rule (Logic)</strong></p>
</blockquote>
<ul>
<li>컴퓨터 프로그램에서 실세계의 규칙에 따라 <strong>데이터를 생성, 표시, 저장, 변경</strong>하는 부분</li>
<li>UI (Presentation tier) 와 DB (Data tier) 사이에서 발생한 정보 교환을 위한 특정 알고리즘이나 규칙이 정의된 tier
<img src="https://velog.velcdn.com/images/ve_hye_ona/post/3d84fda6-a7b1-44ac-989a-b6884443d68c/image.png" alt=""></li>
</ul>
<br>

<h2 id="clean-architecture">Clean Architecture</h2>
<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/fa2b4b35-be9b-4c56-9b68-16fa0e5ded1a/image.png" alt=""></p>
<p>크게 Domain, Infrastructure, 그 사이의 Adapter로 구분되어 있고 각 layer는 세분화되어 있다.</p>
<p>위 그림 또한 Dependecy Rule에 따라 작동하여 outer에서 inner로 의존성을 가지게 된다.</p>
<h3 id="domain">Domain</h3>
<p>Business rule이 존재하는 영역</p>
<ul>
<li>잘 변하지 않는 안정된 영역</li>
</ul>
<h4 id="entities">Entities</h4>
<p>Application에서 핵심적인 기능인 Business Rule들을 담고 있음</p>
<ul>
<li>Class 내의 method 들의 그룹으로 볼 수 있다.</li>
</ul>
<h4 id="use-cases">Use Cases</h4>
<p>특정 Application에 대한 Business Rule로써, Entity를 사용하여 시스템이 어떻게 자동화될 것인지에 대해 정의하고 Application의 행위를 결정함</p>
<ul>
<li>Abstract class나 interface를 정의한다.</li>
</ul>
<h3 id="interface-adapter">(Interface) Adapter</h3>
<p>Domain과 Infrastructure 사이의 경계를 관리하는 영역</p>
<h4 id="controllers">Controllers</h4>
<h4 id="gateways">Gateways</h4>
<h4 id="presenters">Presenters</h4>
<h3 id="infrastructure">Infrastructure</h3>
<p><strong>UI, DB, web APIs</strong>, Devices,** Frameworks**, External Interfaces 등이 존재하는 영역</p>
<ul>
<li>Domain에 비해 자주, 쉽게 바뀔 수 있는 영역</li>
</ul>
<br>

<h3 id="ref">Ref</h3>
<p><a href="https://k-elon.tistory.com/38">https://k-elon.tistory.com/38</a></p>
<p>의존성 역전 원칙 (DIP) <a href="https://huisam.tistory.com/entry/DIP">https://huisam.tistory.com/entry/DIP</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring Controller, Service, DAO, Repository, DTO, Entity(Domain), VO, DB]]></title>
            <link>https://velog.io/@ve_hye_ona/Spring-controller-service-DAO-repository-DTO-VO-entity</link>
            <guid>https://velog.io/@ve_hye_ona/Spring-controller-service-DAO-repository-DTO-VO-entity</guid>
            <pubDate>Sun, 18 Dec 2022 05:58:58 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/b222a9ae-d8a4-4666-a4b7-01d02fa8218b/image.png" alt=""></p>
<h1 id="controller">Controller</h1>
<p>주로 사용자의 요청을 처리한 후 지정된 뷰에 모델 객체를 넘겨주는 역할로
사용자의 요청이 진입하는 지점으로 요청에 따라 어떤 처리를 할지 결정을 Service에 넘겨줌</p>
<p>; <strong>Client의 요청</strong>을 받았을 때 그 요청에 대해 <strong>실제 업무를 수행하는 Service를 호출</strong>하고</p>
<ul>
<li>클라이언트가 보낸 데이터가 있다면 호출 시 전달하기 쉽게 데이터 가공</li>
</ul>
<p><strong>모델의 업무 수행이 완료</strong>되면 그 결과를 바탕으로 화면을 구성하도록 <strong>View에 전달</strong>함</p>
<h1 id="service">Service</h1>
<p>비즈니스 로직을 수행하고 DB에 접근하는 DAO를 이용해서 결과값을 받아 와 처리한 내용을 View에 넘겨줌</p>
<p>; Controller의 요청을 받아 알맞은 정보를 가공하여 Controller에게 재전달</p>
<ul>
<li>Repository를 상속받아 관련 함수 사용이 가능</li>
</ul>
<h1 id="dao-data-access-object">DAO (Data Access Object)</h1>
<p>DB에 접근하기 위한 객체</p>
<ul>
<li><p>영속성 객체를 숨기지 않음; 구현체가 인프라 계층에 있다는 것을 숨기지 않음</p>
</li>
<li><p>서비스와 DB를 연결하기 위한 중간 다리</p>
</li>
<li><p>JPA는 매우 적은 코드로 DAO를 구현할 수 있도록 해줌</p>
</li>
</ul>
<h1 id="repository">Repository</h1>
<p>DB에 접근하기 위한 객체이자 객체의 상태를 관리하는 저장소로 <strong>영구 저장소가 아닌 객체의 상태를 관리</strong>하는 저장소</p>
<p>; Entity에 의해 생성된 DB에 접근하는 메서드를 사용하기 위한 <strong>인터페이스</strong></p>
<ul>
<li>인프라 계층이 아니라 도메인 계층</li>
<li>영속성 객체임을 숨김; 구현체가 인프라 계층에 숨겨져 있음</li>
<li><strong>JPA</strong>를 상속받음으로써 기본적인 <strong>CRUD 동작</strong>이 가능해짐</li>
</ul>
<h1 id="dto-data-transfer-object">DTO (Data Transfer Object)</h1>
<p>계층(Layer)간 데이터 교환을 위해 사용하는 객체</p>
<ul>
<li><p>데이터 교환만을 위해 사용하므로 로직을 가지지 않고, getter/setter 메소드만 갖는다.</p>
</li>
<li><p>뷰에서 컨트롤러로 넘어오는 데이터를 담거나, 컨트롤러에서 서비스로 넘기는 데이터를 담거나 할 때 사용</p>
</li>
</ul>
<h1 id="entity-domain">Entity (Domain)</h1>
<p><strong>DB 테이블</strong> 내에 존재하는 Column만을 속성(field)로 가지는 클래스</p>
<p>; DB 테이블과 매핑되며 실제 DB에 저장되는 내용들을 구현하는 class (Entity Table)</p>
<ul>
<li>PK (id)로 구분</li>
<li>상속을 받거나 구현체여서는 안됨</li>
<li>Setter를 사용하면 안됨</li>
<li>로직을 가질 수 있음</li>
</ul>
<h1 id="db">DB</h1>
<h1 id="vo-value-object">VO (Value Object)</h1>
<p>값 그 자체를 표현하는 객체</p>
<ul>
<li>로직을 포함할 수 있음</li>
<li>객체의 불변성을 보장함; 객체의 정보가 변경되지 않음</li>
</ul>
<br>

<h1 id="-practice">+ Practice</h1>
<p>Qvest의 oms 프로젝트 중 백엔드 task인 help.oms API를 개발하게 되면서 알게 된 점을 간단하게나마 정리한다.</p>
<p>CRUD 기반 REST API를 Spring으로 구현한 일반적인 형태는 다음 실습 참고 Github 소스를 참고하면 좋을 것 같다. 
Entity, DTO, Repository, Service, Controller(아래 소스에서는 Resource)를 비교적 잘 구분해놓았기 때문에 각각의 개념과 쓰임을 익히는데 도움이 될 것 같다.</p>
<ul>
<li><a href="https://github.com/pedrohenriquelacombe/spring-rest-crud-example">실습 참고 Github 소스</a></li>
</ul>
<p>다만 해당 코드가 이번 task를 진행하면서 Abstraction을 좀 더 잘 지키기 위해 작성한 코드와 조금 다른 건, Service에 대해 Service Interface와 Service 하위 Package로 Implementation(<strong>ServiceImpl</strong>)이 존재하지 않고 바로 Service Class를 구현하였다는 점 정도인 것 같다.</p>
<br>

<h3 id="ref">Ref</h3>
<p><a href="https://velog.io/@jybin96/Controller-Service-Repository-%EA%B0%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C">https://velog.io/@jybin96/Controller-Service-Repository-%EA%B0%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C</a></p>
<p><a href="https://plo-developdiary.tistory.com/m/62">https://plo-developdiary.tistory.com/m/62</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Interface]]></title>
            <link>https://velog.io/@ve_hye_ona/Interface</link>
            <guid>https://velog.io/@ve_hye_ona/Interface</guid>
            <pubDate>Thu, 15 Dec 2022 05:18:13 GMT</pubDate>
            <description><![CDATA[<h3 id="개념과-역할">개념과 역할</h3>
<p>극단적으로 동일한 목적 하에 동일한 기능을 수행하게끔 강제하는 것이 바로 인터페이스의 역할이자 개념이다. </p>
<p>interface를 이용하여 <strong>개발 코드를 직접 수정하지 않고도 사용하고 있는 객체만 변경할 수 있도록</strong> 할 수 있다.
즉 <strong>자바의 다형성을 극대화</strong>하여 개발코드 수정을 줄이고 프로그램 유지보수성을 높이기 위해 인터페이스를 사용한다.</p>
<h3 id="특징">특징</h3>
<ul>
<li><p>추상 메서드를 가진다.</p>
</li>
<li><p>변수를 만들면 자도응로 앞에 public static final이 생략된다.</p>
</li>
<li><p>인터페이스를 메모리에 로드하려면 익명 클래스를 만든다.</p>
</li>
<li><p>추상 method는 무조건 child가 구현해야 한다.</p>
</li>
<li><p>함수를 넘길 때 사용하며, class와 다르게 행위가 정해져 있지 않을 때 사용한다.</p>
</li>
</ul>
<br>

<h3 id="ref">Ref</h3>
<p><a href="https://interconnection.tistory.com/129">https://interconnection.tistory.com/129</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Enum]]></title>
            <link>https://velog.io/@ve_hye_ona/Enum</link>
            <guid>https://velog.io/@ve_hye_ona/Enum</guid>
            <pubDate>Thu, 15 Dec 2022 04:59:30 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Java version 1.5부터 도입된 서로 연관된 상수들의 집합인 열거형 클래스</p>
</blockquote>
<h3 id="ex">Ex.</h3>
<pre><code>enum Status {
    PROCEEDING, COMPLETE;
}</code></pre><p>=</p>
<pre><code>class Status {
    public static final Status PROCEEDING = new Status();
    public static final Status COMPLETE = new Status();
}</code></pre><h3 id="필요성">필요성</h3>
<p>기존의 String type의 상수는</p>
<pre><code>public static final String</code></pre><p>으로 정의하였는데, 런타임 에러 등 프로그램의 치명적인 오작동을 초래할 수 있다는 문제점을 해결하기 위해 활용한다.</p>
<p>이를 활용하면
코드가 단순해지며 가독성이 향상되고,
instance 생성과 상속을 방지하여 컴파일 시 상수값의 type stability가 보장된다.</p>
<br>

<h3 id="ref">Ref</h3>
<p><a href="https://mangkyu.tistory.com/73">https://mangkyu.tistory.com/73</a></p>
<p><a href="https://mangkyu.tistory.com/74">https://mangkyu.tistory.com/74</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP vs SSE vs WebSocket]]></title>
            <link>https://velog.io/@ve_hye_ona/HTTP-vs-WebSocket</link>
            <guid>https://velog.io/@ve_hye_ona/HTTP-vs-WebSocket</guid>
            <pubDate>Sun, 11 Dec 2022 08:16:19 GMT</pubDate>
            <description><![CDATA[<p>Qvest Flutter App에 Alpaca로부터 가져온 실시간 데이터를 수신하여 표시해주어야 하는 task를 진행하게 되었다.
이는 Http와 Websocket이 어떻게 다른지 공부하는 기회가 되었는데 이를 통해 정리한 바를 기록으로 남긴다.</p>
<br>

<p>실시간 데이터 전송에 사용되는 HTTP 프로토콜과 WebSocket 프로토콜에 대해 알아보고 이를 비교한다.
추가적으로 SSE 기술에 대해서도 알아볼 것이다.</p>
<h1 id="http">HTTP</h1>
<p>기본적으로 HTTP Protocol은 비연결성의 특징을 가지기 때문에, 실시간 통신에는 적합하지 않은데 이를 구현하는 3가지 방식은 다음과 같다.</p>
<h2 id="polling">Polling</h2>
<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/5df89086-8d71-4fee-bc75-56f29a496577/image.png" alt=""></p>
<p>브라우저가 일정한 주기마다 서버에 HTTP request를 보내는 방식</p>
<ul>
<li>HTTP가 클라이언트에서 서버로만 요청이 가기 때문에 <strong>이벤트가 없어도 주기적으로 서버에 요청</strong>을 보내 업데이트가 있는지 확인하고 있다면 업데이트 시킴</li>
<li>클라이언트가 주기적으로 서버에 request를 보내므로 부담이 큼</li>
<li>실시간 데이터의 업데이트 주기는 예측 불가능하여 불필요한 요청에 따른 <strong>서버 및 네트워크의 부하</strong>가 늘어남</li>
<li>time interval에 따라 서버의 부하가 커지거나 실시간성이 떨어지는 문제가 발생</li>
</ul>
<p>&lt;활용&gt; 실시간성이 중요하지 않거나 time interval을 늘려 여러 대의 client와 통신할 때 사용</p>
<h2 id="long-polling">Long Polling</h2>
<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/4e7bb746-327f-47a6-925f-9c23aa911af3/image.png" alt=""></p>
<p>polling의 서버 부하를 줄이면서 실시간성을 높이기 위한 방식</p>
<ul>
<li>HTTP 요청 시 서버는 해당 연결을 바로 해제하지 않고 일정 시간 대기함. 이 동안 <strong>데이터 업데이트가 일어나면(이벤트)</strong> 바로 클라이언트에게 response를 보내고 전달 받은 데이터를 처리함. 그리고 응답을 받은 클라이언트는 서버에 다시 request를 보냄</li>
<li><strong>응답이 와 연결이 끊기면</strong> 클라이언트가 서버에 다시 연결 request를 하므로 <strong>클라이언트의 부담이 줄어듦</strong></li>
<li><strong>잦은 데이터 변경이 발생하면 서버의 부담</strong>이 커짐</li>
<li>일반 polling 방식보다는 서버의 부담이 줄겠지만 데이터 업데이트가 빈번해지면 일반 polling 방식과 차이가 큰 차이가 없음</li>
</ul>
<p>&lt;활용&gt; 실시간성이 필요한 적은 수의 클라이언트와 연결되어 있는 경우에 사용</p>
<h2 id="streaming">Streaming</h2>
<p>요청에 대한 응답을 완료하지 않은 상태에서 데이터를 계속 내려받는 방식으로 응답을 받더라도** 연결을 끊고 다시 request를 보내는 과정이 없고** 계속 응답을 받아 처리하는 방식</p>
<ul>
<li>long polling의 연결구축에 대한 부하를 해결하는 방식</li>
<li>서버는 무한정 / 일정 시간동안 클라이언트의 요청을 대기시키고 chunked 메세지를 통하여 응답 시 연결을 계속 유지함</li>
<li><strong>클라이언트에서 서버로 데이터를 보내는 게 힘들</strong>기 때문에 실시간 양방향 통신이 아니라 실시간 단방향 통신이 주로 이뤄짐</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/25a6bba3-6b08-4ff0-929b-be3de9e725b2/image.png" alt=""></p>
<h1 id="server-sent-event-sse">Server Sent Event (SSE)</h1>
<ul>
<li>EventSource 객체를 이용해 처음 한 번만 연결하면 서버가 클라이언트에게 지속적으로 데이터를 보내줌</li>
<li>클라이언트는 서버로부터 데이터만 받을 수 있음</li>
<li>접속에 문제가 있으면 자동으로 재연결을 시도하지만 클라이언트가 페이지를 닫아도 서버에서 감지하기 어려움</li>
<li>HTTP/1.1의 경우 브라우저당 6개의 접속만을 허가하며 HTTP/2에서는 100개까지의 접속을 허용</li>
<li>알람과 같이 서버에서 단방향으로 보내는 이벤트들에 유리함</li>
</ul>
<h1 id="websocket">WebSocket</h1>
<p><strong>실시간 양방향</strong> 데이터 전송을 위한 기술</p>
<ul>
<li><strong>ws/wss 프로토콜</strong> 사용<ul>
<li>ws 프로토콜을 지원하지 않는 오래된 브라우저에서는 사용할 수 없음</li>
<li>Ex. Node.js : ws나 Socket.IO와 같은 패키지를 통해 웹 소켓 사용 가능</li>
</ul>
</li>
<li>Full-Duplex (전이중) 방식</li>
<li>클라이언트와 서버 간 양방향 통신이 가능</li>
<li>불필요한 요청(한 번의 요청) / 응답 헤더 데이터가 존재하지 않음</li>
<li><strong>최초 WebSocket 연결(접속)은 Http 요청인 Handshaking을 활용</strong></li>
<li>TCP 연결임에도 Byte stream만이 아닌 UTF-8의 Text와 Binary 모두를 보낼 수 있음</li>
<li>실시간성이 강조될 때, Http보다 빠른 Websocket을 사용</li>
<li>HTTP와 포트 공유가 가능하며 좋은 성능을 보여줌</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/fae26bad-1ea4-4fc0-bb42-3824b0c24951/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/bb500eac-508c-4841-86b0-156d14d6be1c/image.png" alt=""></p>
<h1 id="정리">정리</h1>
<p><img src="https://velog.velcdn.com/images/ve_hye_ona/post/6cc8f688-a17d-4bb4-a175-e1f52d477171/image.png" alt=""></p>
<br>
<br>

<h1 id="-httphttps-vs-wswss">+ http/https VS ws/wss</h1>
<p>http : 일반적인 http 프로토콜
https : 데이터 보안을 위해 SSL을 적용한 http 프로토콜</p>
<p>ws : 일반적인 ws 프로토콜
wss : 데이터 보안을 위해 SSL을 적용한 ws 프로토콜</p>
<h3 id="ref">REF</h3>
<p><a href="https://www.joinc.co.kr/w/man/12/websocket">https://www.joinc.co.kr/w/man/12/websocket</a> </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Lombok 라이브러리]]></title>
            <link>https://velog.io/@ve_hye_ona/Java-Lombok</link>
            <guid>https://velog.io/@ve_hye_ona/Java-Lombok</guid>
            <pubDate>Sun, 11 Dec 2022 07:27:47 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Annotation 기반으로 코드를 자동완성해주는 library</p>
</blockquote>
<h3 id="필요성">필요성</h3>
<p>getter, setter, toString 등 여러 코드의 (반복적인) 생성 없이 코드를 자동 완성시킴으로써
코드 생산성을 향상시키고,
가독성 및 유지 보수성을 향상시키고,
그 외에도 builder 패턴이나 로그 생성 등 다양한 방면으로 활용 가능하다.</p>
<br>

<h3 id="ref">REF</h3>
<p>lombok 사용 방법 참고
<a href="https://mangkyu.tistory.com/78">https://mangkyu.tistory.com/78</a> </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JPA (Java Persistence API)]]></title>
            <link>https://velog.io/@ve_hye_ona/JPA-Java-Persistence-API</link>
            <guid>https://velog.io/@ve_hye_ona/JPA-Java-Persistence-API</guid>
            <pubDate>Fri, 11 Nov 2022 08:56:33 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Java 언어에서의 <strong>Object-Relational Mapping (ORM)</strong> 기술 표준으로 사용되는 인터페이스의 모음으로 구현된 클래스와 매핑을 해주기 위해 사용되는 프레임워크</p>
</blockquote>
<blockquote>
<p><strong>ORM</strong>
Application class와 관계형 데이터베이스 (Relational Database)의 테이블을 매핑한다는 뜻으로, 기술적으로는 application의 객체를 RDB 테이블에 자동으로 영속화해주는 것</p>
</blockquote>
<h4 id="필요성">필요성</h4>
<h5 id="배경--패러다임의-불일치">배경 : 패러다임의 불일치</h5>
<pre><code>현재의 개발 언어 트렌드 : Java, Scala, Kotlin과 같은 객체 지향 언어
현재의 데이터베이스 세계 : Oracle, MySQL, PostgreSQL과 같은 RDB

&gt; 추상화, 캡슐화, 정보은닉, 상속, 다형성 등 시스템의 복잡성을 제어할 수 있는 객체지향개발에 비해,
관계형 데이터베이스의 경우 데이터를 잘 정규화해서 저장하는 것이 목표</code></pre><p>객체를 RDB에 관리해야 하기 때문에 개발자 입장에서는 SQL 중심적인 개발 (개발자가 객체를 SQL로 변환해서 RDB에 저장하는 변환 과정을 직접 해야 함)이 된다는 문제가 있다.</p>
<h4 id="역할">역할</h4>
<p>JPA는 반복적인 CRUD SQL을 처리해준다.
따라서 어떤 SQL이 실행될지만 생각하면 된다.</p>
<blockquote>
<p>CRUD = CREATE + READ + UPDATE + DELETE
대부분의 컴퓨터 소프트웨어가 가지는 기본적인 데이터 처리 기능</p>
</blockquote>
<p>이를 통해 궁극적으로는 SQL이 아닌 객체 중심의 개발이 가능해진다는 점으로 생산성이 나아지고 유지보수도 수월해진다.</p>
<h5 id="생산성-향상">생산성 향상</h5>
<pre><code>JPA를 사용함으로써 지루하고 반복적인 코드를 개발자가 직접 작성하지 않아도 되고, DDL문도 자동 생성해주기 때문에 DB 설계 중심을 객체 설계 중심으로 변경할 수 있다.</code></pre><h5 id="유지보수성-향상">유지보수성 향상</h5>
<pre><code>필드를 하나만 추가해도 관련 SQL문과 JDBC 코드를 전부 수정해야 하는 번거로움이 있었는데 JPA가 이를 대신 처리해준다.
DB가 변경되더라도 JPA에게 알려주면 비교적 간단하게 수정이 가능하다.</code></pre><h5 id="성능-향상">성능 향상</h5>
<pre><code>- Application과 DB 사이의 성능 최적화 기회를 제공한다.    
- 같은 transaction 안에서는 같은 entity를 반환하기 때문에 DB와의 통신 횟수를 줄일 수 있다.
- transaction을 commit하기 전가지 메모리에 쌓고 한번에 SQL을 전송한다.</code></pre><h5 id="데이터-접근-추상화와-벤더-독립성">데이터 접근 추상화와 벤더 독립성</h5>
<pre><code>RDB는 같은 기능이라도 벤더마다 사용법이 다르기 때문에 처음 선택한 DB에 종속되고 변경이 어려운데, JPA는 application과 DB 사이에서 추상화된 데이터 접근을 제공하기 때문에 종속이 되지 않도록 한다. </code></pre><h2 id="-jpql-java-persistence-query-language">+ JPQL (Java Persistence Query Language)</h2>
<p>JPA에서 제공되는 SQL을 추상화한 형태의 객체 지향 쿼리 언어로
식별자를 통한 단순 조회가 아닌 추가 조건들(query)을 통해 조회를 하고자 할 때 사용</p>
<h3 id="ref">Ref</h3>
<p>JPA, Hibernate, Spring Data JPA 차이
<a href="https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/">https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/</a></p>
<p>JDBC와 Hikari Connection Pool (cp)
<a href="https://velog.io/@miot2j/Spring-DB%EC%BB%A4%EB%84%A5%EC%85%98%ED%92%80%EA%B3%BC-Hikari-CP-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0">https://velog.io/@miot2j/Spring-DB%EC%BB%A4%EB%84%A5%EC%85%98%ED%92%80%EA%B3%BC-Hikari-CP-%EC%95%8C%EC%95%84%EB%B3%B4%EA%B8%B0</a></p>
]]></description>
        </item>
    </channel>
</rss>