<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>s_keyyy.log</title>
        <link>https://velog.io/</link>
        <description>FE Developer🌱</description>
        <lastBuildDate>Wed, 16 Feb 2022 06:55:02 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>s_keyyy.log</title>
            <url>https://images.velog.io/images/s_keyyy/profile/1a17d943-f2d2-4a86-95b6-e0e7c09c4022/6DB405D7-FE76-46A2-830E-9AF1C13CD95B.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. s_keyyy.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/s_keyyy" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Typescript] Non-null assertion operator]]></title>
            <link>https://velog.io/@s_keyyy/Typescript-Non-null-assertion-operator</link>
            <guid>https://velog.io/@s_keyyy/Typescript-Non-null-assertion-operator</guid>
            <pubDate>Wed, 16 Feb 2022 06:55:02 GMT</pubDate>
            <description><![CDATA[<h3 id="non-null-assertion-operator">Non-null assertion operator</h3>
<ul>
<li>!로 표시</li>
<li>해당 연산자가 null, undeifned가 아니라고 지정해주는 것</li>
</ul>
<pre><code class="language-typescript">// emailRef의 타입
// (property) React.RefObject&lt;Input&gt;.current: Input | null
// 예시에서는 null이 아닌 Input으로 타입을 고정하기 위해 사용
const email = emailRef.current!.state.value;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[react에 tailwind css 적용]]></title>
            <link>https://velog.io/@s_keyyy/React-Query</link>
            <guid>https://velog.io/@s_keyyy/React-Query</guid>
            <pubDate>Wed, 12 Jan 2022 13:59:59 GMT</pubDate>
            <description><![CDATA[<ol>
<li>tailwind.css</li>
</ol>
<pre><code class="language-css">@tailwind base;
@tailwind components;
@tailwind utilities;</code></pre>
<ol start="2">
<li>tailwind.config.js<pre><code class="language-javascript">module.exports = {
content: [&#39;./src/**/*.{ts,tsx}&#39;],
theme: {
 extend: {},
},
plugins: [],
};
</code></pre>
</li>
</ol>
<pre><code>3. package.json
```json
  &quot;scripts&quot;: {
    &quot;build:tailwind&quot;: &quot;tailwindcss build src/tailwind.css -o src/tailwind.output.css&quot;,
    &quot;prestart&quot;: &quot;npm run build:tailwind&quot;,
    &quot;start&quot;: &quot;npm run build:tailwind &amp;&amp; react-scripts start&quot;,
    &quot;build&quot;: &quot;react-scripts build&quot;,
    &quot;test&quot;: &quot;react-scripts test&quot;,
    &quot;eject&quot;: &quot;react-scripts eject&quot;
  },</code></pre><ol start="4">
<li>App에 tailwind.output.css import 해주기
<img src="https://images.velog.io/images/s_keyyy/post/138cba6f-43af-44d2-b789-8f5c2c0b0d31/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202022-01-12%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2011.08.41.png" alt=""></li>
</ol>
<p>자주 사용하는 부분만 익히면 반응형으로 적용할 수 있어서 좋지만
컴포넌트별로 스타일링 하기 어려워서 emotion을 쓰는게 더 나은거 같기도 함!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux] mount 설정]]></title>
            <link>https://velog.io/@s_keyyy/Linux-mount-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@s_keyyy/Linux-mount-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Sun, 14 Nov 2021 12:25:36 GMT</pubDate>
            <description><![CDATA[<p>임대한 HDD 스토리지를 디렉토리에 연결해주기 위해 mount 설정해줌</p>
<ol>
<li>fdisk -l 디스크 조회</li>
<li>fdisk /폴더명 파티션 생성</li>
<li>mount /폴더명 /mount할 폴더명</li>
<li>df -Th 확인</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux] crontab 스케줄러]]></title>
            <link>https://velog.io/@s_keyyy/Linux-crontab-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%9F%AC</link>
            <guid>https://velog.io/@s_keyyy/Linux-crontab-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%9F%AC</guid>
            <pubDate>Tue, 14 Sep 2021 11:16:22 GMT</pubDate>
            <description><![CDATA[<h3 id="1-txt-이나-csv-확장자로-데이터-수집">1. .txt 이나 .csv 확장자로 데이터 수집</h3>
<h3 id="2-sh-스크립트-작성">2. sh 스크립트 작성</h3>
<pre><code class="language-shell">#!/bin/bash
echo $(date +&quot;%Y-%m-%d %H:%M:%S&quot;)&#39; start&#39;
&quot;파이썬.exe 경로&quot; &quot;파일.py 경로&quot;   # python일 경우
php 파일.php 경로               # php일 경우
echo $(date +&quot;%Y-%m-%d %H:%M:%S&quot;)&#39; end&#39;</code></pre>
<pre><code class="language-shell">#!/bin/sh
echo $(date +&quot;%Y-%m-%d %H:%M:%S&quot;)&#39; start&#39;
mysql -uusername -ppassword &lt; 파일명.sql
echo $(date +&quot;%Y-%m-%d %H:%M:%S&quot;)&#39; end&#39;
echo &quot;================ sql done =============&quot;</code></pre>
<h3 id="3-sql-파일-작성">3. .sql 파일 작성</h3>
<pre><code class="language-sql">use 데이터베이스명;

LOAD DATA INFILE &#39;파일경로/파일명&#39;
INTO TABLE 테이블명 
FIELDS TERMINATED BY &#39;,&#39;        
ENCLOSED BY &#39;&quot;&#39;         
LINES TERMINATED BY &#39;\n&#39;    
IGNORE 1 LINES                  
(컬럼명, 컬럼명 ...);</code></pre>
<h3 id="4-log파일-생성값-입력x">4. .log파일 생성(값 입력X)</h3>
<ul>
<li>파일 권한 설정 해주기 chmod<h3 id="5-스케줄러-설정">5. 스케줄러 설정</h3>
<pre><code class="language-shell">crontab -e
</code></pre>
</li>
</ul>
<h1 id="8시간-마다-실행">8시간 마다 실행</h1>
<ul>
<li>*/8 * * * 경로/파일명.sh &gt;&gt; 경로/파일명.log 2&gt;&amp;1</li>
</ul>
<p>crontab -l  # 설정한 크론탭 확인</p>
<p>```
log파일 열어보면 스케줄러 제대로 작동하고 있는지 확인 가능하다.
<img src="https://images.velog.io/images/s_keyyy/post/282c15c7-1791-44fe-8f0c-d9a6b098a621/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-09-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.31.13.png" alt="로그파일"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[MSA] 깊게 살펴보기]]></title>
            <link>https://velog.io/@s_keyyy/MSA-%EA%B9%8A%EA%B2%8C-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0</link>
            <guid>https://velog.io/@s_keyyy/MSA-%EA%B9%8A%EA%B2%8C-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0</guid>
            <pubDate>Thu, 22 Jul 2021 05:18:12 GMT</pubDate>
            <description><![CDATA[<h2 id="msa">MSA</h2>
<ul>
<li>빠르게 개발하여 지속적을 배포가 가능</li>
<li>명확한 API를 통해 높은 확장성 -&gt; 인스턴스 추가 시 수동으로 로드밸런서를 구성 해 주어햐 한다는 단점 존재</li>
</ul>
<h3 id="궁금점🤔">궁금점🤔</h3>
<blockquote>
<p>무상태 프로그래밍
아무것도 공유하지 않는 아키텍처를 유지
 데이터베이스의 데이터를 공유하지 않음</p>
</blockquote>
<p>Q. 모든 요청에 맞게 적용되야 하는 확정성이 있는데 이게 공유되는 거지 않는가? 무상태라고 할 수 있을까?</p>
<p>A. 데이터를 공유하지 않는것이지 요청을 공유하는 것과는 별개라고 생각</p>
<h2 id="msa-디자인패턴">MSA 디자인패턴</h2>
<h3 id="서비스-검색">서비스 검색</h3>
<h3 id="에지-서버">에지 서버</h3>
<p>.... 좀 더 공부하고 정리하기</p>
<p>스프링부트 , 스프링 웹플럭스, 스프링 데이터 등..</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[OAuth]]></title>
            <link>https://velog.io/@s_keyyy/OAuth</link>
            <guid>https://velog.io/@s_keyyy/OAuth</guid>
            <pubDate>Sat, 10 Jul 2021 11:30:39 GMT</pubDate>
            <description><![CDATA[<h1 id="oauth-flow">OAuth flow</h1>
<p><img src="https://images.velog.io/images/s_keyyy/post/142bfac3-0145-4258-8d88-dc47ad6142f9/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-07-10%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.29.35.png" alt="OAuth flow"></p>
<p>사용자가 로그인을 눌러서 구글 프로필을 얻게 됨
사용자가 다시 로그인을 할 때 구글 프로필을 다시 얻게 되고
아이디를 이전에 로그인 했던 것과 비교
<img src="https://images.velog.io/images/s_keyyy/post/3c3ce677-7b5d-45bf-9eb0-424ca3e4a95f/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-07-10%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.33.35.png" alt="">
profile에 있는 id를 token으로 사용</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Node] 개념]]></title>
            <link>https://velog.io/@s_keyyy/Node-%EA%B0%9C%EB%85%90</link>
            <guid>https://velog.io/@s_keyyy/Node-%EA%B0%9C%EB%85%90</guid>
            <pubDate>Tue, 22 Jun 2021 10:26:58 GMT</pubDate>
            <description><![CDATA[<p>브라우저의 자바스크립트...?</p>
<p>모듈이란 특정한 기능을 하는 함수나 변수들의 집합이다.</p>
<p>모듈 =&gt; 파일</p>
<p>노드에서는 대부분의 파일이 다른 파일을 모듈로 사용하고 있음</p>
<h1 id="내장객체">내장객체</h1>
<p>노드에서는 기본적인 내장 객체와 내장 모듈을 제공
브라우저의 window 객체와 비슷</p>
<blockquote>
<p>node는 dom이나 window 대신에 gloabal 이라는 전역객체 존재</p>
</blockquote>
<blockquote>
<p>Note ≡ setImmediate(콜백)과 setTimeout(콜백, 0)
setImmediate(콜백)과 setTimeout(콜백, 0)에 담긴 콜백 함수는 이벤트 루프를 거친 뒤 즉시 실행됩니다. 둘의 차이점은 무엇일까요? 특수한 경우에 setImmediate는 setTimeout(콜백, 0)보다 먼저 실행됩니다. 파일 시스템 접근, 네트워킹 같은 I/O 작업의 콜백 함수 안에서 타이머를 호출하는 경우입니다. 하지만 setImmediate가 항상 setTimeout(콜백, 0)보다 먼저 호출되지는 않는다는 사실만 알아두세요. 헷갈리지 않도록 setTimeout(콜백, 0)은 사용하지 않는 것을 권장합니다.</p>
</blockquote>
<p>export.odd = &quot;&quot;;
exports에는 반드시 객체처럼 속성명과 속성값을 대입</p>
<pre><code class="language-javascript">// 함수 식
// 화살표 함수의 this는 바로 상위 스코프의 this와 같다.
const whatIsThis = () =&gt; {
    console.log(&#39;function&#39;, this === exports, this === global);
};

// 함수 선언문
// this = 전역
function whatIsThis2() {
    console.log(&#39;function&#39;, this === exports, this === global);
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Redux] toolkit- createAsyncThunk]]></title>
            <link>https://velog.io/@s_keyyy/%E3%85%87</link>
            <guid>https://velog.io/@s_keyyy/%E3%85%87</guid>
            <pubDate>Sat, 08 May 2021 13:03:03 GMT</pubDate>
            <description><![CDATA[<p><a href="https://redux-toolkit.js.org/api/createAsyncThunk">https://redux-toolkit.js.org/api/createAsyncThunk 참고</a></p>
<h1 id="createasyncthunk">createAsyncThunk</h1>
<p>action type을 문자열로 받아들이고 Promise를 리턴하는 콜백함수다.
전달받은 action type에 따라 action types을 생성하고,
Promise콜백을 실행하고 dispach한 thunk action creator를 리턴한다.
비동기 처리시 추천</p>
<pre><code class="language-javascript">export const userLogin = createAsyncThunk(&#39;users/siginup&#39;, async (arg) =&gt; {
    const res = await UserService.siginin(arg);
    return res.data;
});</code></pre>
<h3 id="parameter">parameter</h3>
<h4 id="1-문자열-action-type">1. 문자열 action type</h4>
<p>비동기 요청이 올 때 대표되는 액션 타입 constant</p>
<h4 id="2-payloadcreator">2. payloadCreator</h4>
<ul>
<li><p>비동기 로직의 결과를 포함하여 리턴하는 콜백함수(근데 동기적인 것도 리턴할 수 있음)</p>
<blockquote>
<p>It may also return a value synchronously. If there is an error, it should either return a rejected promise containing an Error instance or a plain value such as a descriptive error message or otherwise a resolved promise with a RejectWithValue argument as returned by the thunkAPI.rejectWithValue function.</p>
</blockquote>
</li>
</ul>
<ul>
<li><p>두개의 argument 존재</p>
<ul>
<li>thunkAPI : thunk함수에 전달되는 모든 파라미터를 포함하는 객체</li>
<li>arg : a single value 
첫번째 파라미터는 dispatch되면 thunk action creator를 지나간다. 
한가지 요청일 때 편리, 
만약에 여러 value라면 object로 만들어서 dispatch하면 된다.<pre><code class="language-javascript">dispatch(userSignup(userInfo));</code></pre>
</li>
</ul>
</li>
</ul>
<h4 id="3options-object">3.options object</h4>
<p>(생략가능해 보인다)</p>
<h3 id="return-value">return value</h3>
<p>returns a standard Redux thunk action creator</p>
<h3 id="promise">promise</h3>
<p>createAsyncThunk는 createAction을 사용하여 세 개의 Redux 액션 생성자를 생성한다.pending, fulfilled, rejected 이 3가지들을 핸들하기 위해서는 builder 콜백을 통해서 가능하다.</p>
<pre><code class="language-javascript">extraReducers: (builder) =&gt; {
  builder.addCase(userSignup.fulfilled, (state, { payload }) =&gt; {
    return [...payload];
  });
},</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring security]]></title>
            <link>https://velog.io/@s_keyyy/Spring-security</link>
            <guid>https://velog.io/@s_keyyy/Spring-security</guid>
            <pubDate>Fri, 07 May 2021 00:29:36 GMT</pubDate>
            <description><![CDATA[<h1 id="spring-security">Spring security</h1>
<ul>
<li>filter</li>
<li>interceptor</li>
</ul>
<pre><code class="language-java">implementation &#39;org.springframework.boot:spring-boot-starter-security&#39;
implementation &#39;org.springframework.security:spring-security-test&#39;</code></pre>
<h3 id="모놀리식에서의-위치">모놀리식에서의 위치</h3>
<p>web.xml(load-on-startup = servlet-context.xml)
servlet-context(JSP + Controller) ➡️ filter ➡️ Spring의 context(interceptor + beans)</p>
<h3 id="마이크로서비스에서의-위치">마이크로서비스에서의 위치</h3>
<p>--</p>
<h2 id="csrf">CSRF</h2>
<p>CSRF는 쿠키와 세션에 있는 state를 노려서 해킹
이를 방지하기 위해 추가로 CSRF Token을 같이 전송(토큰은 세션(컨트롤러)에 저장)
(브라우저 -&gt; 서버)
근데 이 방식이 보안에 취약하고 이미 뚫려버렸음
CSRF Token대신에 <strong>JWT사용</strong>
JWT =&gt; <strong>Header</strong> / <strong>Payload</strong> / Signature</p>
<blockquote>
<p>리덕스에서 기존 액션이 표준이 아니고, Flex Standard Action 이라는 새로운 액션을 만들어진 이유</p>
</blockquote>
<pre><code class="language-java">implementation group: &#39;io.jsonwebtoken&#39;, name: &#39;jjwt&#39;, version: &#39;0.9.1&#39;</code></pre>
<ol>
<li>JWT 처리</li>
<li>비번 암호화</li>
<li>자동로그인</li>
<li>React 로그인<h2 id="swagger">Swagger</h2>
스웨거는 문서 생성을 위한 webflux
스웨거 기반 어노테이션으로 애플리케이션을 검사한다.</li>
</ol>
<pre><code class="language-java">compile group: &#39;io.springfox&#39;, name: &#39;springfox-swagger2&#39;, version:  &#39;2.9.2&#39;
compile group: &#39;io.springfox&#39;, name: &#39;springfox-swagger-ui&#39;, version:  &#39;2.9.2&#39;
implementation group: &#39;javax.validation&#39;, name: &#39;validation-api&#39;, version: &#39;2.0.1.Final&#39;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] Stream]]></title>
            <link>https://velog.io/@s_keyyy/Java-Stream</link>
            <guid>https://velog.io/@s_keyyy/Java-Stream</guid>
            <pubDate>Tue, 27 Apr 2021 09:48:30 GMT</pubDate>
            <description><![CDATA[<h1 id="stream">Stream</h1>
<p>데이터타입을 추상화하여 배열, 컬렉션 등을 모두 같은 방식으로 다룰 수 있게 하는 방법</p>
<blockquote>
<p>Stream = 끊이지않고 객체가 계속 움직이는 것</p>
</blockquote>
<h2 id="특징">특징</h2>
<ul>
<li>불변성 =&gt; flux패턴</li>
<li>일회용 =&gt; 무상태</li>
<li>내부 반복 처리 =&gt; map(), forEach()</li>
<li>지연된 연산 =&gt; Lazy(메모리 점유를 하지 않는다)</li>
</ul>
<pre><code class="language-java">// StreamUtil.java
public class StreamUtil {
    public List&lt;String&gt; arrayToList(String... arr){
        return Arrays.asList(arr).stream().collect(Collectors.toList());
    }
}

// StreamMain.java
public class StreamMain {
    public static void main(String... args) {
        new StreamUtil()
                .arrayToList(new String[] {&quot;a&quot;, &quot;c&quot;, &quot;d&quot;})
                .forEach(System.out::println);
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[AWS] RDS 생성]]></title>
            <link>https://velog.io/@s_keyyy/AWS-RDS-%EC%83%9D%EC%84%B1</link>
            <guid>https://velog.io/@s_keyyy/AWS-RDS-%EC%83%9D%EC%84%B1</guid>
            <pubDate>Tue, 27 Apr 2021 02:35:24 GMT</pubDate>
            <description><![CDATA[<h1 id="rds-생성">RDS 생성</h1>
<ul>
<li><p>꼭 <strong>프리 티어</strong>로 변경하기!!
<img src="https://images.velog.io/images/s_keyyy/post/338f302f-24d0-49fd-9d0a-a367ff91d539/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-04-26%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2012.05.47.png" alt="rds 설정 화면"></p>
</li>
<li><p>DB인스턴스 식별자, 마스터 사용자 이름, 마스터암호 설정</p>
</li>
<li><p>보안 그룹 생성
<img src="https://images.velog.io/images/s_keyyy/post/4973e54e-fcc1-40d6-95cc-754b6fbab809/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-04-26%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2012.54.29.png" alt="보안그룹">
  -인바운드
<img src="https://images.velog.io/images/s_keyyy/post/2ed82045-225d-4800-be22-5b41f1600f82/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-04-26%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2012.43.23.png" alt="보안그룹 설정"></p>
</li>
<li><p>파라미터도 생성하여 추가해주기
<img src="https://images.velog.io/images/s_keyyy/post/4adfaeaf-fe04-466e-a36d-df4c680abd5d/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-04-26%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%2012.54.34.png" alt="파라미터"></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Redux Toolkit]]></title>
            <link>https://velog.io/@s_keyyy/Redux-Toolkit</link>
            <guid>https://velog.io/@s_keyyy/Redux-Toolkit</guid>
            <pubDate>Thu, 22 Apr 2021 08:33:25 GMT</pubDate>
            <description><![CDATA[<h1 id="redux-toolkit">Redux Toolkit</h1>
<blockquote>
<p>Creating a slice requires a string name to identify the slice, an initial state value, and one or more reducer functions to define how the state can be updated. Once a slice is created, we can export the generated Redux action creators and the reducer function for the whole slice</p>
</blockquote>
<h2 id="fsaflux-standard-actions">FSA(Flux Standard Actions)</h2>
<p>액션 생성자는 type과 payload를 포함하여 액션을 생성</p>
<h2 id="createslice">createSlice()</h2>
<blockquote>
<p>A function that accepts an initial state, an object full of reducer functions, and a &quot;slice name&quot;, and automatically generates action creators and action types that correspond to the reducers and state.</p>
</blockquote>
<p>슬라이스는 이름, 초기상태, 리듀서로 이루어진 객체
createAction()과, createReducer()가 합쳐진 형태</p>
<pre><code class="language-javascript">// redux toolkit boilerplate
import {createSlice} from &#39;@reduxjs/toolkit&#39;;

const sliceReducer = createSlice({
    name : &#39;&#39;,
    initialState: {},
    reducers: {}
});

// 구조분해할당
const {actions, reducer} = sliceReducer
export {} = actions;
export default reducer;</code></pre>
<h1 id="todolist-예제">TodoList 예제</h1>
<h2 id="구조">구조</h2>
<p>📦src
 ┣ 📂todo
 ┃ ┣ 📂component
 ┃ ┃ ┣ 📜AddTodo.js
 ┃ ┃ ┣ 📜DeleteTodo.js
 ┃ ┃ ┣ 📜DoneTodo.js
 ┃ ┃ ┣ 📜EditTodo.js
 ┃ ┃ ┣ 📜Todo.js
 ┃ ┃ ┗ 📜Todos.js
 ┃ ┣ 📂container
 ┃ ┃ ┗ 📜TodoApp.js
 ┃ ┣ 📂reducer
 ┃ ┃ ┗ 📜todo.slice.js
 ┃ ┣ 📂service
 ┃ ┃ ┗ 📜Todo.service.js
 ┃ ┣ 📂style
 ┃ ┃ ┗ 📜Todo.css
 ┃ ┗ 📜index.js
 ┣ 📜App.js
 ┗ 📜index.js</p>
<h2 id="reducer">reducer</h2>
<pre><code class="language-jsx">const initialState = {
  todolist: [],
};

const todoSlice = createSlice({
  name: &#39;todoSlice&#39;,
  initialState,
  reducers: {
    editTodo(state, { payload }) {
      console.log(&#39;edit todo&#39;);
      const editId = state.todolist.find((todo) =&gt; todo.id === payload);
      editId.text = payload.text;
    },
    addTodo(state, { payload }) {
      state.todolist.push({ id: uuid(), text: payload, done: false });
    },
    toggleTodo(state, { payload }) {
      const toggle = state.todolist.find((todo) =&gt; todo.id === payload);
      toggle.done = !toggle.done;
    },
    allDeleteTodo(state, { payload }) {
      state.todolist.splice(payload);
    },
    deleteTodo(state, { payload }) {
      const idx = state.todolist.findIndex((todo) =&gt; todo.id === payload);
      state.todolist.splice(idx, 1);
      /*
            *********filter 사용하는 방법**********
            state.todolist = state.todolist.filter(
                (todo) =&gt; todo.id !== payload
            );
            */
    },
  },
});</code></pre>
<p>reducer는 순수함수이기 때문에 Immutable해야 함
그래서 initialState를 해치치 않고 새로운 state를 리턴</p>
<h2 id="container">container</h2>
<p>부모 컴포넌트 -&gt; 자식 컴포넌트 : 버블링
자식 컴포넌트 -&gt; 부모 컴포넌트 : 캡쳐링</p>
<p><img src="https://images.velog.io/images/s_keyyy/post/b2aaf0a5-9aad-41b9-a531-19f8e5fb58c6/todoapp.png" alt="app"></p>
<p>useSelector를 통해 reducer의 state를 구독하는 리스너 생성
상태를 props로 전달 
-&gt; Todo.js, Todos.js에서는 전달받은 props를 배열함수 map을 사용해서 값 할당</p>
<h2 id="component">component</h2>
<p><img src="https://images.velog.io/images/s_keyyy/post/bd984b0b-fc01-4a13-8749-71139a57d57a/add.png" alt="add">
이벤트가 실행되면 ready였던 프로세스가 running되어야 하기 때문에 dispatch를 사용
dispatch()안에는 action메소드가 들어있는데 reducer에서 선언되어있던 action을 실행</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Redux]]></title>
            <link>https://velog.io/@s_keyyy/Redux</link>
            <guid>https://velog.io/@s_keyyy/Redux</guid>
            <pubDate>Tue, 20 Apr 2021 03:54:42 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><a href="https://redux.js.org">https://redux.js.org 참고</a>
Redux Toolkit을 사용하지 않은 Vanila Redux로 일단 개념 잡기</p>
</blockquote>
<h1 id="redux를-사용하는-이유">Redux를 사용하는 이유</h1>
<p>함수형 프로그램밍을 해야 하는데 리액트는 클로저함수 구조 
그래서 pure함수인 리덕스가 필요</p>
<p>리턴의 형태가 (...)</p>
<pre><code class="language-jsx">const test = () =&gt; {
    return(&lt;&gt;&lt;/&gt;)
}</code></pre>
<p>리듀서는 function object 순수함수 구조 
순수함수는 외부(리액트)의 상태를 변경하지 않으면서 동일한 인자에 대해 항상 똑같은 값을 리턴
리턴의 형태{...}</p>
<pre><code class="language-javascript">const todoApp = (state = {}, action) =&gt;{
  return {
    todos: todos(state.todos, action),
    visibilityFilter: visibilityFilter(state.visibilityFilter, action)
  }
}</code></pre>
<h1 id="flux-pattern">Flux Pattern</h1>
<p>Flux는 MVC와 다르게 단방향으로 데이터가 흐른다
action -&gt; dispatch -&gt; store &lt;-&gt; view</p>
<h1 id="redux">Redux</h1>
<blockquote>
<p>A Predictable State Container for JS Apps</p>
</blockquote>
<p>리덕스는 <strong>상태 컨테이너</strong>다.</p>
<blockquote>
<p>global state of your app is stored in an object tree inside <strong>a single store</strong>. The only way to change the state tree is to create an <strong>action</strong>, an object describing what happened, and dispatch it to the store. To specify how state gets updated in response to an action, you write pure reducer functions that calculate a new state based on the old state and the action.</p>
</blockquote>
<ul>
<li>스토어는 1개</li>
<li>트리 안에 객체가 있는데 그 객체는 상태</li>
<li>트리구조 ⇒ 그래프구조(노드+엣지)<ul>
<li>반드시 Root 를 가진다(리액트는 컴포넌트 트리구조, 리덕스는 리듀서 트리구조)<pre><code class="language-javascript">// 상태 객체(트리)구조
{
todos: [{
text: &#39;Eat food&#39;,
completed: true
}, {
text: &#39;Exercise&#39;,
completed: false
}],
visibilityFilter: &#39;SHOW_COMPLETED&#39;
}</code></pre>
</li>
</ul>
</li>
<li>상태트리(=객체트리)를 변경하는 유일한 방법은 액션객체를 parameter로 전달하는 것</li>
<li>상태를 바꾸기 위해서는 바로 변경해서는 안되고 액션을 통해 상태 변경을 정의</li>
<li>reducer를 통해 변경이 작성</li>
</ul>
<p>=&gt; 상태, 액션은 객체, 전체 상태를 변경하기 위해서 reducer 함수를 사용하는데 이때 상태를 변경하는 것은 액션이다.</p>
<blockquote>
<p>To change something in the state, you need to dispatch an action</p>
</blockquote>
<p><a href="https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4">디스패치</a> = 준비 상태에서 실행 상태로 바뀌는 것
dispatch (processname) : ready → running</p>
<h2 id="store">store</h2>
<p>객체
상태컨테이너
store 안에는 state, action, reducer가 있다.
<a href="https://ko.wikipedia.org/wiki/%EC%8B%B1%EA%B8%80%ED%84%B4_%ED%8C%A8%ED%84%B4">Singleton Pattern</a></p>
<h3 id="state">state</h3>
<p>스토어 안에 있는 객체
global state</p>
<h3 id="action">action</h3>
<p>reducer를 호출하는 객체
상태를 바꾸는 것 type이라는 key가 있다. ⇒ state key가 된다.</p>
<pre><code class="language-javascript">{ type: &#39;ADD_TODO&#39;, text: &#39;Go to swimming pool&#39; }
{ type: &#39;TOGGLE_TODO&#39;, index: 1 }
{ type: &#39;SET_VISIBILITY_FILTER&#39;, filter: &#39;SHOW_ALL&#39; }</code></pre>
<p>action이 호출 될 때 마다 해당하는 상태를 변경하는 것 =&gt; <a href="https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%BD%94%EB%A0%88%EC%9D%B4%ED%84%B0_%ED%8C%A8%ED%84%B4">Decoration Pattern</a></p>
<h3 id="reducer">reducer</h3>
<p>스테이트를 변경하는 함수</p>
<blockquote>
<p>not mutate the state object, but return a new object if the state changes</p>
</blockquote>
<p>(state, action) ⇒ 변경된state</p>
<h2 id="handleactions">handleActions()</h2>
<p>action의 type에 따라 작업</p>
<h2 id="usedispatch">useDispatch()</h2>
<pre><code class="language-javascript">const dispatch = useDispatch();

const onIncrease = useCallback(() =&gt; {
  dispatch(increase());
}, [dispatch]);</code></pre>
<p>리덕스에서 만들어 둔 액션들 중에서 리액트가 골라서 디스패치에 담아서 리덕스로 보낸다.
디스패치는 프로세스 상태를 ready에서 running으로 바꾸는 것
onIncrease 이벤트가 발생하면 스토어에서 선언되었던 increase 메소드를 호출</p>
<h2 id="useselector">useSelector()</h2>
<p>store의 state를 리스너(=구독)하는 메소드</p>
<pre><code class="language-javascript">const number = useSelector(state =&gt; state.counterReducer.number);</code></pre>
<h1 id="의문점이-있었는데-해결">의문점이 있었는데 해결</h1>
<pre><code class="language-javascript">const number = useSelector((state) =&gt; {
       console.log(state);
});</code></pre>
<p>이렇게 콘솔 찍어보면 counterReducer가 출력된다.
<img src="https://images.velog.io/images/s_keyyy/post/2e206359-8ca7-47b2-b380-e05cabcd7d78/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-04-20%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%208.14.33.png" alt="콘솔창">
그렇다면 counterReducer 메소드 내부의 state를 참조 할 수 있다는 건데 useSelector에 state.counterReducer라고 리턴을 정의해주지 않았는데? 어떻게?</p>
<pre><code class="language-javascript">const counterReducer = handleActions({...});</code></pre>
<blockquote>
<p><a href="https://react-redux.js.org/api/hooks">react-redux 참고</a>
useSelector() will also subscribe to the <strong>Redux store</strong>, and run your selector whenever an action is dispatched.</p>
</blockquote>
<p>현재 내가 작성한 store에</p>
<pre><code class="language-jsx">export default counterReducer;</code></pre>
<p>로 하였고, useSelector()의 state parameter는 store를 말하기 때문이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Closure, Lexical environment]]></title>
            <link>https://velog.io/@s_keyyy/Closure-Lexical-environment</link>
            <guid>https://velog.io/@s_keyyy/Closure-Lexical-environment</guid>
            <pubDate>Mon, 19 Apr 2021 00:33:16 GMT</pubDate>
            <description><![CDATA[<h1 id="closure">Closure</h1>
<p><strong>함수형 프로그래밍에서의 객체다.</strong></p>
<blockquote>
<p>“A closure is the combination of a function and the <strong>lexical environment</strong> within which that function was declared.”</p>
</blockquote>
<p>함수가 선언됐을 때의 렉시컬 환경(Lexical environment)과의 조합이다.</p>
<p><a href="https://poiemaweb.com/js-closure">https://poiemaweb.com/js-closure 참고</a></p>
<h2 id="lexical-environment">Lexical environment</h2>
<p>함수형 프로그래밍에서 객체(함수, {...}, 스크립트)는 렉시컬 환경이라 불리는 internal hidden associated object를 갖는다.</p>
<ul>
<li>Lexical = field</li>
<li>environment = valiable 공간</li>
</ul>
<pre><code class="language-javascript">const Test = () =&gt; {
      // Lexical environment
    return (
        &lt;&gt;
            &lt;h2&gt;테스트&lt;/h2&gt;
        &lt;/&gt;
    );
};
</code></pre>
<p>react에서의 컴포넌트를 예시로 들어보면 Lexical environment의 영역은 다음과 같다. 기능과 속성의 집합이기 때문에 Test 컴포넌트는 객체다.</p>
<p>함수형 프로그래밍은 객체를 멀리하여야 한다.
하지만 react는 클로저 형태이기 때문에 객체다.</p>
<p>...? 무상태프로그래밍을 해야 하는데 말이 되지 않는다.</p>
<p>그래서 함수형프로그램이 가능하게 하기 위해서 <strong>객체가 아닌 함수 = 순수함수</strong>가 필요하다.
그래서 나온게 Redux</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[마이크로서비스 아키텍처, 모놀리식 아키텍처]]></title>
            <link>https://velog.io/@s_keyyy/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%AA%A8%EB%86%80%EB%A6%AC%EC%8B%9D-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98</link>
            <guid>https://velog.io/@s_keyyy/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C%EC%84%9C%EB%B9%84%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%AA%A8%EB%86%80%EB%A6%AC%EC%8B%9D-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98</guid>
            <pubDate>Thu, 15 Apr 2021 09:38:58 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>스프링으로 하는 마이크로서비스 구축 책 참고</p>
</blockquote>
<h1 id="마이크로서비스-아키텍처">마이크로서비스 아키텍처</h1>
<p>backend, frontend 나눠서 개발</p>
<ul>
<li>프로젝트의 기능들을 작고 독립적이며 느슨하게 결합 된 모듈로 분해</li>
<li>2개 이상 서버와 DB를 사용하는 방식</li>
<li>서버를 여러개 운영하기 때문에 모놀리식보다 유지비용이 많이 든다.</li>
<li>취약한 보안</li>
<li>개발환경 인프라 구성 : <strong>클라우드 방식</strong></li>
</ul>
<blockquote>
<p>클라우드 방식은 아마존, 구글 등 클라우드 서비스를 임대하여 개발 환경을 구축하는 방식</p>
</blockquote>
<ul>
<li><p>stateless</p>
</li>
<li><p>async</p>
</li>
<li><p>개별적인 런타임 프로세스</p>
<ul>
<li>Java -&gt; Tomcat</li>
<li>JavaScript -&gt; NPM</li>
</ul>
</li>
</ul>
<h2 id="그래프구조">그래프구조</h2>
<p><img src="https://images.velog.io/images/s_keyyy/post/f5ef3205-d61c-40c2-98bb-f0703db5d6a5/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-04-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.27.11.png" alt="node-edge"></p>
<p>node를 edge로 연결 하는데 그 가운데에 <strong>에지 서버</strong>가 존재</p>
<ul>
<li>에지 서버는 리버스 프록시로 동작</li>
<li>동적 로드 밸런싱 기능을 제공하고자 검색 서비스와 통합</li>
</ul>
<p>모든 요청이 담겨야 하는 공간이기 때문에 컨테이너가 있어야 한다.
SpringBoot 노드와 React노드 사이에 존재하는 에지 서버는 Tomcat
= RESTful 방식</p>
<blockquote>
<p>자바에서 edge = path
React에서 edge = routing</p>
</blockquote>
<h2 id="pub-sub구조">Pub-Sub구조</h2>
<blockquote>
<p>개발된 각 컴포넌트는 WAR파일로 패키징해서 톰캣과 같은 웹 컨테이너에 배포된다.</p>
</blockquote>
<ul>
<li><p>웹 컨테이너 : web(html) + container(컴포넌트의 집합)</p>
</li>
<li><p>배포 : Pub-Sub구조</p>
<ul>
<li>Pub-Sub구조 : 비동기 메시징 패러다임</li>
</ul>
</li>
</ul>
<p><img src="https://images.velog.io/images/s_keyyy/post/c5b3897a-8641-4f8b-be03-7b125eb373e6/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-04-15%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.16.37.png" alt="Pub-Sub구조"></p>
<h2 id="scale-out">Scale out</h2>
<p>서버를 추가하는 방식(Scale을 Vector화 시키는 것)
마이크로서비스 아키텍처는 <strong>플랫폼API</strong>에 맞추어 작업하기 때문에 <strong>수평 스케일링</strong>이 가능</p>
<h2 id="마이크로서비스-디자인-패턴">마이크로서비스 디자인 패턴</h2>
<p>스프링부트, 스프링 클라우드, 쿠버네티스</p>
<h1 id="모놀리식-아키텍처">모놀리식 아키텍처</h1>
<p>Spring MVC</p>
<ul>
<li>1개의 서버와 DB를 사용하는 방식
합쳐져 있기 때문에 개발이 용이하고 보안이 좋다.
그래서 은행에서는 모놀리식 방법을 사용</li>
<li>개발환경 인프라 구성 : 온프레미스 방식<blockquote>
<p>온프레미스는 인트라넷망을 활용하여 개발환경을 구축하는 방식</p>
</blockquote>
</li>
</ul>
<h4 id="추가">추가</h4>
<p><em>Spring과 Jsp
servlet = Server + let
scriptlet = Script + let
let은 작은조각들
원래 server와 script는 한 몸인데 조각들로 이루어져 있기 때문에
따로 fetch, axios 없이 getAttribute로 데이터 응답과 요청이 잘 적용되었던 것</em></p>
<p><img src="https://images.velog.io/images/s_keyyy/post/472a1fab-28d2-4107-9eaa-6a013a70c1d0/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-04-14%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%206.53.40.png" alt="webapp">
Spring MVC모델로 설계를 하면 view는 webapp이라는 폴더 아래에 저장하게 된다.
여기서 webapp은 web(html) + app(java) 을 말한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[BoilerPlate]]></title>
            <link>https://velog.io/@s_keyyy/BoilerPlate</link>
            <guid>https://velog.io/@s_keyyy/BoilerPlate</guid>
            <pubDate>Wed, 14 Apr 2021 09:45:43 GMT</pubDate>
            <description><![CDATA[<h1 id="보일러플레이트">보일러플레이트</h1>
<p>재사용 할 수 있고, 비슷한 형태의 코드를 반복적으로 사용하는 것을 말한다.</p>
<h2 id="spring-boot에서의-보일러플레이트">Spring boot에서의 보일러플레이트</h2>
<p>=&gt; <a href="start.spring.io">start.spring.io</a>를 통해 생성</p>
<h3 id="jpa에서의-보일러플레이트">JPA에서의 보일러플레이트</h3>
<p>=&gt; <a href="https://spring.io/projects/spring-data-jpa">Spring Data JPA</a>의 <a href="https://github.com/spring-projects/spring-data-examples/tree/master/jpa/java8/src/main/java/example/springdata/jpa/java8">깃헙</a>을 살펴보면 domain과 repository가 있어야 하는 것을 알 수 있다.</p>
<h2 id="react에서의-보일러플레이트">React에서의 보일러플레이트</h2>
<p>=&gt; CRA 명령어를 통해 생성</p>
<blockquote>
<p>보일러플레이트에는 프로토콜에 대한 설정이 녹아있다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Error] MySQL syntax error]]></title>
            <link>https://velog.io/@s_keyyy/Error-Mybatis</link>
            <guid>https://velog.io/@s_keyyy/Error-Mybatis</guid>
            <pubDate>Tue, 13 Apr 2021 06:49:11 GMT</pubDate>
            <description><![CDATA[<p><a href="https://sdevstudy.tistory.com/22">참고블로그 https://sdevstudy.tistory.com/22</a></p>
<p>Address와 AddressFile 2개의 테이블을 매핑한 후 글을 작성하는 기능을 구현하려고 했다.</p>
<p><img src="https://images.velog.io/images/s_keyyy/post/517d4df8-04de-425a-b9d0-f19be77aab14/%E1%84%89%E1%85%B3%E1%84%8F%E1%85%B3%E1%84%85%E1%85%B5%E1%86%AB%E1%84%89%E1%85%A3%E1%86%BA%202021-04-13%20%E1%84%8B%E1%85%A9%E1%84%92%E1%85%AE%203.06.32.png" alt=""></p>
<p>seq가 있을 경우에는 문제 없이 데이터가 삽입 되지만
값이 없을 경우에는 id를 선택을 할 수 없어 다음과 같은 오류가 발생한다.</p>
<pre><code>Could not set property &#39;id&#39; of &#39;class com.test.domain.Address&#39;
with value &#39;null&#39; Cause: java.lang.IllegalArgumentException</code></pre><p>처음에 작성한 sql은 다음과 같다. </p>
<pre><code class="language-mysql">select max(id)+ 1 from ADDRESS</code></pre>
<p>0일 경우에는 1로 시작하고 그 이후에는 max(id)를 찾아서 1씩 증가시켜 주는 조건이 있어야 한다.
그래서 <strong>ifnull</strong> 문법을 추가하니 데이터가 없을 때도 문제 없이 추가 되었다.</p>
<pre><code class="language-mysql">select ifnull(max(id)+ 1,1) from ADDRESS</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Error] Spring에서 @GetMapping, @PostMapping 적용안되는 경우]]></title>
            <link>https://velog.io/@s_keyyy/Error-Spring%EC%97%90%EC%84%9C-GetMapping-PostMapping-%EC%A0%81%EC%9A%A9%EC%95%88%EB%90%98%EB%8A%94-%EA%B2%BD%EC%9A%B0</link>
            <guid>https://velog.io/@s_keyyy/Error-Spring%EC%97%90%EC%84%9C-GetMapping-PostMapping-%EC%A0%81%EC%9A%A9%EC%95%88%EB%90%98%EB%8A%94-%EA%B2%BD%EC%9A%B0</guid>
            <pubDate>Thu, 08 Apr 2021 00:52:31 GMT</pubDate>
            <description><![CDATA[<p>Spring Boot에서 잘 적용되던 @GetMapping, @PostMapping 어노테이션이 Spring에서는 적용이 되지 않았다.</p>
<p>구글링해보니 ** 레거시 프로젝트일 경우 sts3을 사용하기 때문에 
org.springframework-version을 변경해주어야 한다**고한다.</p>
<p>나 같은 경우는 sts4에 마켓플레이스로 sts3를 다운받아서 사용하고 있었서 상관 없다고 생각했는데 version이 3으로 되어 있어서 다음과 같이 변경해주니 정상적으로 잘 적용됐다.</p>
<pre><code class="language-xml">&lt;properties&gt;
  &lt;java-version&gt;11&lt;/java-version&gt;
  &lt;org.springframework-version&gt;5.0.7.RELEASE&lt;/org.springframework-version&gt;
  &lt;org.aspectj-version&gt;1.9.0&lt;/org.aspectj-version&gt;
  &lt;org.slf4j-version&gt;1.7.25&lt;/org.slf4j-version&gt;
&lt;/properties&gt;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Linux] 18.04 Ubuntu 설치방법]]></title>
            <link>https://velog.io/@s_keyyy/Linux-18.04-Ubuntu-%EC%84%A4%EC%B9%98%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@s_keyyy/Linux-18.04-Ubuntu-%EC%84%A4%EC%B9%98%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Thu, 18 Mar 2021 16:05:10 GMT</pubDate>
            <description><![CDATA[<h2 id="파티션-분할">파티션 분할</h2>
<p>D드라이브 만들기(100G 이상으로 잡는 것이 좋다)</p>
<h2 id="ubuntu-download">Ubuntu Download</h2>
<p>18.04 Ubutu 64-bit PC (AMD64) desktop image 다운</p>
<h2 id="usb-시동-디스크-만들기">USB 시동 디스크 만들기</h2>
<p><a href="https://www.techspot.com/downloads/6153-universal-usb-installer.html">Universal USB Installer</a> UUI 다운(버전: 2.0.0.0)</p>
<blockquote>
<p>USB를 꽂은 상태에서 진행하기</p>
</blockquote>
<ol>
<li>Select a Distriution from the dropdown to put on your USB - Ubuntu 선택</li>
<li>Browse to your ubutnu<em>desktop</em>.iso - 우분투 이미지 선택</li>
<li>USB선택</li>
<li>Fat32 Format Drive를 선택</li>
<li>Create</li>
</ol>
<h2 id="bios-접속">BIOS 접속</h2>
<p>f2연타하여 접속
UEFI Boot Order를 USB(시동 디스크)로 설정</p>
<h3 id="기본-설정">기본 설정</h3>
<p>sudo apt-get update
sudo apt-get install vim
sudo apt-get install git</p>
<h3 id="한글-설정">한글 설정</h3>
<ol>
<li>Language Support 클릭</li>
<li>언어팩 전부 설치 후 재부팅</li>
<li>Settings 에서 Korean(Hangul) 설정</li>
<li>우측 상단에서 en -&gt; 한글 설정</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring boot + React build process]]></title>
            <link>https://velog.io/@s_keyyy/Spring-boot-React-build-process</link>
            <guid>https://velog.io/@s_keyyy/Spring-boot-React-build-process</guid>
            <pubDate>Wed, 17 Mar 2021 13:08:38 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>be, fe 합쳐서 build하는 방법 (21.03.16 기준 오류 없이 작동)
spring boot(Maven) + react 연동</p>
</blockquote>
<ol>
<li>workspace 폴더 만들고 sts 실행</li>
<li>create new Spring starter project</li>
<li>npx create-react-app fe</li>
<li>fe 경로에 yarn add serve</li>
<li>node,yarn 버전 변경 후 maven update
(frontend-maven-plugin, maven-resources-plugin) <a href="https://mvnrepository.com/">플러그인 사용</a><pre><code class="language-xml">// pom.xml
</code></pre>
</li>
</ol>
<properties>
  <java.version>11</java.version>
  <frontend-src-dir>${project.basedir}/fe</frontend-src-dir>
  <node.version>v15.9.0</node.version>
  <yarn.version>v1.22.10</yarn.version>
  <frontend-maven-plugin.version>1.7.6</frontend-maven-plugin.version>
</properties>
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <scope>provided</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>com.github.eirslett</groupId>
    <artifactId>frontend-maven-plugin</artifactId>
    <version>1.11.2</version>
  </dependency>
</dependencies>
<build>
  <plugins>
    <plugin>
      <groupId>com.github.eirslett</groupId>
      <artifactId>frontend-maven-plugin</artifactId>
      <version>${frontend-maven-plugin.version}</version>
      <configuration>
        <nodeVersion>${node.version}</nodeVersion>
        <yarnVersion>${yarn.version}</yarnVersion>
        <workingDirectory>${frontend-src-dir}</workingDirectory>
        <installDirectory>${project.build.directory}</installDirectory>
      </configuration>
      <executions>
        <execution>
          <id>install-frontend-tools</id>
          <goals>
            <goal>install-node-and-yarn</goal>
          </goals>
        </execution>
        <execution>
          <id>yarn-install</id>
          <goals>
            <goal>yarn</goal>
          </goals>
          <configuration>
            <arguments>install</arguments>
          </configuration>
        </execution>
        <execution>
          <id>build-frontend</id>
          <goals>
            <goal>yarn</goal>
          </goals>
          <phase>prepare-package</phase>
          <configuration>
            <arguments>build</arguments>
          </configuration>
        </execution>
      </executions>
    </plugin>
    <plugin>
      <artifactId>maven-resources-plugin</artifactId>
      <version>3.0.1</version>
      <executions>
        <execution>
          <id>position-react-build</id>
          <goals>
            <goal>copy-resources</goal>
          </goals>
          <phase>prepare-package</phase>
          <configuration>
            <outputDirectory>${project.build.outputDirectory}/static</outputDirectory>
            <resources>
              <resource>
                <directory>${frontend-src-dir}/build</directory>
                <filtering>false</filtering>
              </resource>
            </resources>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>
```
6. run as -> maven clean, maven install
7. applicatioin run
8. localhost:8080 접속하면 React화면 출력]]></description>
        </item>
    </channel>
</rss>