<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>박유상의 개발블로그</title>
    <link>https://muhly.tistory.com/</link>
    <description>개발블로그</description>
    <language>ko</language>
    <pubDate>Fri, 19 Jun 2026 12:07:55 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>박유상의 개발블로그</managingEditor>
    <image>
      <title>박유상의 개발블로그</title>
      <url>https://tistory1.daumcdn.net/tistory/3044522/attach/c0b9b319ec6b405b9ecf56cdf0031421</url>
      <link>https://muhly.tistory.com</link>
    </image>
    <item>
      <title>[WEB] REST API 기본</title>
      <link>https://muhly.tistory.com/158</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;HTTP&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트와 서버 사이에 이루어지는 요청 및 응답 프로토콜이다. URL을 통해 정보를 요청하면 요청한 정보를 다시 전달해준다.&lt;br /&gt;주로 웹 환경에서 사용 되는 프로토콜로, IOT 등에는 적합하지 않다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;API (Application Programming Interface)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 애플리케이션에서 사용할 수 있도록, 특정 환경의 기능을 제어할 수 있게 만든 인터페이스이다. 우리가 흔히 접하는 구글지도API 등은 구글지도의 기능을 다른 애플리케이션에서 제어할 수 있게 만든 인터페이스라고 쉽게 생각할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;REST API (Representational State Transfer)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;HTTP의 장점을 최대한 활용하기 위해 고안된 REST 아키텍쳐 스타일을 따르는 API이다. 클라이언트와 서버를 명확하게 구분할 수 있으며 서버에서 특별한 상태를 저장할 필요가 없다. 즉, 서버에서는 들어오는 요청을 단순히 처리하면 되고 클라이언트에서는 정해진 규격에 따라 요청만 하면 된다. 또, HTTP에서 사용하는 Cache를 사용하여 응답을 저장해 불필요한 재 요청을 방지할 수&amp;nbsp; 있다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;REST API와 HTTP API (즉, 웹 API)는 거의 같은 의미로 사용되고 있지만 실제로는 아래의 4가지 원칙이 지켜져야한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;자원의 식별&lt;/li&gt;
&lt;li&gt;메세지를 통한 리소스 조작&lt;/li&gt;
&lt;li&gt;자기 서술적 메시지&lt;/li&gt;
&lt;li&gt;애플리케이션 상태에 대한 엔진으로서 하이퍼미디어(HATEOAS)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Method&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크게 아래의 4가지 method가 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;GET&lt;/i&gt; (데이터 요청)&lt;/li&gt;
&lt;li&gt;&lt;i&gt;POST&lt;/i&gt; (새로운 데이터 생성)&lt;/li&gt;
&lt;li&gt;&lt;i&gt;PUT&lt;/i&gt; (데이터 update)&lt;/li&gt;
&lt;li&gt;&lt;i&gt;DELETE&lt;/i&gt; (데이터 삭제)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 &lt;i&gt;Patch&lt;/i&gt;를 &lt;i&gt;Put&lt;/i&gt; 대신 사용하기도 하는데, &lt;i&gt;Put&lt;/i&gt;은 데이터가 존재하지 않으면 데이터를 생성하고, &lt;i&gt;Patch&lt;/i&gt;는 데이터를 업데이트 하기만 한다. 따라서, &lt;i&gt;Put&lt;/i&gt;은 데이터의 모든 요소를 클라이언트가 전송해야하며 &lt;i&gt;Patch&lt;/i&gt;는 수정할 요소와 index만 클라이언트가 가지고 있으면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 말해 &lt;i&gt;Patch&lt;/i&gt;는 데이터를 부분적으로 변경하고, &lt;i&gt;Put&lt;/i&gt;은 데이터 전체를 변경한다. 그러나 하나의 규약일 뿐이지 꼭 지킬 필요는 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Convention&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. URL Router에는 Action(or State)에 대한 정의는 들어가서는 안되며, Resoure는 명사로 표현한다.&lt;/p&gt;
&lt;pre id=&quot;code_1673704362676&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;GET /user/get/:id (X)

GET /user/:id (O)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 특정 Resource의 하위에 존재하는 요소&lt;/p&gt;
&lt;pre id=&quot;code_1673704528766&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/Resource/ID/Element
GET /user/:id/files

/Resource/Sub/Element
GET /user/:id/favorite/artists&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 밑줄 대신 하이픈(_)을 주로 사용하고 소문자를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Request&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API를 제어하기 위해 Request 객체에 보다 상세한 정보를 담는다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;Param&lt;/i&gt; (Router에서 :id의 형태로 표현되는 부분)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1673708065951&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;GET /user/:id/info

localhost:3021/user/3412/info&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;Query&lt;/i&gt; (주로 GET에서 자세한 요청을 전송할 때 사용)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1673708213580&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;GET /artist/list

localhost:3021/artist/list?genre=rock&amp;amp;country=kr&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;i&gt;Body &lt;/i&gt;(JSON 형태로 Query와 다르게 URL에는 보이지 않음)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1673708456394&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;POST /user/signup

localhost:3021/user/signup

Request payload
{
	id : pitterpark
    pw : 1234
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로는 Get, Delete에는 &lt;i&gt;Body&lt;/i&gt;를 넘겨주는 것 자체가 불가능하다.&lt;/p&gt;</description>
      <category>Programming/Web</category>
      <author>박유상의 개발블로그</author>
      <guid isPermaLink="true">https://muhly.tistory.com/158</guid>
      <comments>https://muhly.tistory.com/158#entry158comment</comments>
      <pubDate>Sun, 15 Jan 2023 00:02:35 +0900</pubDate>
    </item>
    <item>
      <title>[React] 파일 경로를 깔끔하게 정리하기</title>
      <link>https://muhly.tistory.com/155</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트의 규모가 커지다보면 가장 먼저 드는 생각이 파일들의 효율적인 정리이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리할 수 있는 유용하지만 간단한 방법을 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;부모 폴더가 같은 Components&lt;/h3&gt;
&lt;pre id=&quot;code_1661725842892&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { SignInModalBox } from &quot;./SignPage/SignInModal&quot;;
import { SignUpModalBox } from &quot;./SignPage/SignUpModal&quot;;

import { useTable } from &quot;./Hooks/useTable&quot;;
import { useConfiguration } from &quot;./Hooks/useConfiguration&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 처럼 부모 폴더가 같은 컴포넌트를 사용할 때, 컴포넌트 하나 당 import 구문이 한 줄씩 추가된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 정리하기 위해 &lt;i&gt;index.js(ts) &lt;/i&gt;파일을 해당 폴더에 생성해 하위 파일들을 모두 import 및 export 해준다.&lt;/p&gt;
&lt;pre id=&quot;code_1661726167670&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import useTable from './useTable';
import useConfiguration from './useConfiguration';

export {
	useTable,
    useConfiguration
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;특정 경로 단순화 하기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 hooks 폴더의 하위 파일들을 Index로 묶어주었다. 이번에는 hooks 폴더의 경로를 단순화 해보자.&lt;/p&gt;
&lt;pre id=&quot;code_1661726374835&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useDataTable, usePagination, useConfigurations } from '@hooks';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;configuration을 적용하면 위와 같이 특정 폴더나 파일의 경로를 패키지처럼 단순화 시킬 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;jsconfig.json&lt;/i&gt; 혹은 &lt;i&gt;tsconfig.json&lt;/i&gt;를 생성하거나 수정하여 적용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1661726579094&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
    &quot;compilerOptions&quot;: {
	...
    ...
    ..
    &quot;paths&quot;: {
    &quot;@utils/*&quot;: [&quot;common/utils/*&quot;],
    &quot;@hooks&quot;: [&quot;common/hooks/index.ts&quot;],
    &quot;@resources&quot;: [&quot;common/constants/resources.ts&quot;],
    &quot;@types&quot;: [&quot;common/types/index.js&quot;],
    }
    },
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 폴더나 파일을 경로를 단순화 할 수 있다.&lt;span style=&quot;color: #bfc7d5;&quot;&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>React/React Basic</category>
      <category>react</category>
      <author>박유상의 개발블로그</author>
      <guid isPermaLink="true">https://muhly.tistory.com/155</guid>
      <comments>https://muhly.tistory.com/155#entry155comment</comments>
      <pubDate>Mon, 29 Aug 2022 07:43:59 +0900</pubDate>
    </item>
    <item>
      <title>쓰로틀링(throttling)과 디바운싱(debouncing)</title>
      <link>https://muhly.tistory.com/154</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;디바운싱(debouncing)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 이벤트가 호출 되었을 때, timer가 동작 중이라면 제거하고 새롭게 추가하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색어를 검색 창에 입력할 때, 실시간으로 결과가 호출되게 하는 경우 모든 입력이 끝났을 경우에만 API를 호출하는 스킬이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네트워크 비용을 크게 절약하고 효율적으로 프로그램이 동작할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1654522757734&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let timer = null;
inputText.onkeydonw = (event) =&amp;gt; {
	if(timer) //이전에 이벤트가 발생했다면
    	clearTimeout(timer); //이전 이벤트를 지운다.
   	if(event.target.value){
    	timer = setTimeout(() =&amp;gt; {
        //추천 검색어 API 호출
        }, 200);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;쓰로틀링(throttling)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막 함수가 호출된 후 일정 시간이 지나기 전에 다시 호출되지 않도록 하는 스킬이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스크롤 시, 요청 버튼을 클릭한 경우 주로 사용하며 중복 요청이 발생하지 않도록 한다.&lt;/p&gt;
&lt;pre id=&quot;code_1654522925002&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let timer = null;
body.onscroll = (event) =&amp;gt; {
	if(!timer){
    	timer = setTimeout(() =&amp;gt; {
        	timer = null;
            //data load
        }, 200);
    }
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>React/JavaScript</category>
      <category>디바운싱</category>
      <category>쓰로틀링</category>
      <author>박유상의 개발블로그</author>
      <guid isPermaLink="true">https://muhly.tistory.com/154</guid>
      <comments>https://muhly.tistory.com/154#entry154comment</comments>
      <pubDate>Mon, 6 Jun 2022 22:42:32 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 비동기 처리</title>
      <link>https://muhly.tistory.com/153</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;비동기 처리&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;프로그래밍 언어는 동기 적으로 동작한다. '동기적 처리'의 사전적 의미로는 '작업의 요청과 결과가 같은 시간에 발생한다'로 작업이 시작되면 작업이 끝날 때까지 해당 작업의 결과를 기다리는 것을 의미한다. 아래의 그림처럼 먼저 시작된 A가 반환된 이후 B가 실행되는 것이다. A의 수행이 오래 걸린다면 B의 시작도 늦어진다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1698&quot; data-origin-height=&quot;910&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7L8BO/btrD3yqEYRn/SaGHetgEkh7H1GPG3cuFXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7L8BO/btrD3yqEYRn/SaGHetgEkh7H1GPG3cuFXk/img.png&quot; data-alt=&quot;출처 : 엘리스 SW엔지니어 트랙&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7L8BO/btrD3yqEYRn/SaGHetgEkh7H1GPG3cuFXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7L8BO%2FbtrD3yqEYRn%2FSaGHetgEkh7H1GPG3cuFXk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;606&quot; height=&quot;325&quot; data-origin-width=&quot;1698&quot; data-origin-height=&quot;910&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : 엘리스 SW엔지니어 트랙&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;비동기적 처리&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 서버에서 데이터를 받아오는 등의 오래 걸리는 작업을 수행한다면 프로그램이 멈춘 것 처럼 보일 것이다. 비동기적 처리로&amp;nbsp;&lt;b&gt;메인 스레드가 서버로부터 데이터를 받아올 때까지 기다리지 않고 먼저 함수 를 반환하고 그 다음 작업을 수행&lt;/b&gt;한다. 서버에서 데이터가 수신되면 이를 처리하는 Callback이 비동기 환경에서 별도로 실행된다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1668&quot; data-origin-height=&quot;954&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnQv72/btrDYoPQmt0/FQJSG2McZ5m8WRKaeVKBb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnQv72/btrDYoPQmt0/FQJSG2McZ5m8WRKaeVKBb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnQv72/btrDYoPQmt0/FQJSG2McZ5m8WRKaeVKBb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnQv72%2FbtrDYoPQmt0%2FFQJSG2McZ5m8WRKaeVKBb1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;343&quot; data-origin-width=&quot;1668&quot; data-origin-height=&quot;954&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1654356140820&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//비동기로 동작하는 함수
async function requestLogin(id, pw){
	return await Fetch('http://server/login'); //서버로 로그인 요청
}

function login(inputId, inputPw){
	requestLogin(inputId, inputPw).then(response=&amp;gt;console.log(response));
    
    return '로그인이 요청되었습니다.';
}

function main(){
	console.log(login('코딩으로세계정복', '123123'));
 	history.push('/home');
    console.log('메인 화면으로 이동');
}

main();

//console ====================
//로그인이 요청되었습니다.
//메인 화면으로 이동
//User('코딩으로세계정복')&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음의 예시를 살펴보자. login 함수는 requestLogin 이라는 비동기 함수를 호출하고 '로그인이 요청되었습니다'를 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main 함수는 login 함수의 반환 값을 받고 메인 화면으로 이동한다. 이 동안, requestLogin 함수는 서버로 로그인을 요청 후 기다리고 있었다. 그리고 서버로부터 로그인이 완료된 유저 데이터를 받아 반환한다. 그러면 login에서 호출한 requestLogin 뒤에 있는&amp;nbsp;then()가 비동기 함수의 응답 처리를 하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;자바스크립트의 비동기&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1748&quot; data-origin-height=&quot;822&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NhHC2/btrD6xk1RSo/C9IqqlWOE7iLXuipi9gJKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NhHC2/btrD6xk1RSo/C9IqqlWOE7iLXuipi9gJKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NhHC2/btrD6xk1RSo/C9IqqlWOE7iLXuipi9gJKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNhHC2%2FbtrD6xk1RSo%2FC9IqqlWOE7iLXuipi9gJKk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1748&quot; height=&quot;822&quot; data-origin-width=&quot;1748&quot; data-origin-height=&quot;822&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트는 단일 스레드로 동작하며, 비동기 환경이 별도로 존재한다. &lt;i&gt;비동기 환경&lt;/i&gt;은 엔진 외부에 위치하며 Event Loop, Task Queue, Job Queue 등으로 구성된다.&amp;nbsp; setTimeout, Fetch 등 기본으로 제공되는 API 함수나 Promise, Async로 비동기를 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;비동기 처리는 우선순위가 가장 높은 &lt;i&gt;JobQueue&lt;/i&gt;에서 작동하며, 요청 처리 후 &lt;i&gt;TaskQueue&lt;/i&gt;에 비동기 응답을 처리하는 &lt;i&gt;Callback&lt;/i&gt; 함수를 넣는다.&lt;/li&gt;
&lt;li&gt;자바스크립트 엔진은 메인스레드의 &lt;i&gt;CallStack&lt;/i&gt;이 비워지면 &lt;i&gt;TaskQueue&lt;/i&gt; 내의 &lt;i&gt;Callback&lt;/i&gt; 함수를 메인스레드에서 실행한다.&lt;/li&gt;
&lt;li&gt;비동기 처리를 받지 않더라도, 모든 Callback 함수는 비동기 환경의 TaskQueue에 넣어졌다가, &lt;i&gt;CallStack&lt;/i&gt;이 비워지면 CallStack으로 이동되어 처리된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Promise&lt;/h2&gt;
&lt;pre id=&quot;code_1654518478981&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const promise = new Promise((resolve, reject) =&amp;gt; {
  setTimeout( function() {
    if(Math.random() &amp;gt; 0.5){ 
    	resolve(&quot;성공&quot;) //랜덤 값이 0.5이상인 경우 성공
    }else{
    	reject(&quot;실패&quot;) //아니라면 실패
    }
  }, 250)
})

promise.then((message) =&amp;gt; { //Then으로 성공의 경우를 응답 처리
  console.log(&quot;0.5 이상이므로&quot; + successMessage);
}).catch((message) =&amp;gt; { //catch로 실패의 경우를 응답 처리
  console.log(&quot;0.5 이하이므로&quot; + successMessage);
}).finally() =&amp;gt; {
  console.log(&quot;Promise 종료&quot;);
};
//Promise chaining이라고 한다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 함수는 &lt;i&gt;Promise&lt;/i&gt;를 반환한다. &lt;i&gt;Promise&lt;/i&gt;는 비동기 작업을 진행, 성공, 실패의 상태로 표현하는 자바스크립트 객체이다. API를 개발하는 경우 주로 사용하며 함수 내부에서 &lt;i&gt;resolve&lt;/i&gt;, &lt;i&gt;reject&lt;/i&gt;로 비동기 동작의 상태를 값과 함께 반환할 수 있다. 함수 밖에서는 &lt;i&gt;then&lt;/i&gt;, &lt;i&gt;catch&lt;/i&gt;, &lt;i&gt;finally&lt;/i&gt;로 비동기의 상태에 따른 처리를 &lt;i&gt;Callback&lt;/i&gt; 함수와 함께 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1661735140330&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function isNotNull(value){
  if(value) return Promise.resolve(true);
  return Promise.reject(false);
}

isNotNull(null).then((e)=&amp;gt;console.log('true')).catch((e)=&amp;gt;console.log('false'))
//false&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같이 사용할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Promise all&lt;/h4&gt;
&lt;pre id=&quot;code_1659346472478&quot; class=&quot;coffeescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Promise.all([promise1, promise2, promise3]).then((values) =&amp;gt; {
  console.log(values);
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 Promise가 해결될 때까지 기다리고, 하나라도 실패 시 가장 먼저 실패한 Promise의 실패 이유를 반환한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Async, Await&lt;/h2&gt;
&lt;pre id=&quot;code_1654519311457&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async function requestLogin(){
	try{
        const data = await fetch(...); //서버에 요청하는 부분
        return data;
    }catch(e){
    	throw new Error('test');
    }
}

requestLogin().then((e)=&amp;gt;{...}).catch((e)=&amp;gt;{...});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 비동기 함수를 함수 내부에서 사용하는 경우 위와 같이 &lt;i&gt;Async&lt;/i&gt;-&lt;i&gt;Await&lt;/i&gt;을 사용해 동기 코드처럼 순차적으로 표현할 수 있다. Promise를 사용하는 경우와 다른 점은 &lt;i&gt;return&lt;/i&gt;이 resolve의 역할을 한다는 것이고 일반적으로 &lt;i&gt;try-catch&lt;/i&gt;를 reject 대신 사용을 한다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마찬가지로 &lt;i&gt;Promise&lt;/i&gt;를 반환하기 때문에 &lt;i&gt;then&lt;/i&gt;, &lt;i&gt;catch&lt;/i&gt;, &lt;i&gt;finally&lt;/i&gt;로 반환 값을 처리할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>React/JavaScript</category>
      <category>async/await</category>
      <category>비동기</category>
      <author>박유상의 개발블로그</author>
      <guid isPermaLink="true">https://muhly.tistory.com/153</guid>
      <comments>https://muhly.tistory.com/153#entry153comment</comments>
      <pubDate>Mon, 6 Jun 2022 21:45:30 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] This 포인터 이해하기</title>
      <link>https://muhly.tistory.com/152</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;This 포인터&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;앞서 This 포인터가 포함된 실행 Context와 Scope에 대해 알아보았다. This로 특정 위치를 참조 할 수 있다. 클래스 내부를 참조할 때 this를 함께 사용함을 본적이 있을 것이다. 또, 일반 함수형과 화살표 함수의 큰 차이점이 바로 이 this 포인터이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1654533030282&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function myFunc(){
	console.log(&quot;myFunc called&quot;);
}

myFunc(); //함수 직접 호출

const o ={
    name : 'Daniel',
    printName : function(){
   		console.log(this.name)}
}

o.printName(); //객체릐 메서드를 호출&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1654533098845&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Person(name){
    this.name = name
    this.printName = function() {
    console.log(this.name)}
}

const p = new Person('Daniel') //생성자 호출

setTimeout(p.printName.bind(p), 1000)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;일반함수에서 &lt;i&gt;this&lt;/i&gt;는 호출한 곳을 가리키며 default(일반적인 사용)는 window(global)이다.&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체가 가진 함수를 호출하는 경우에는 객체 자체가 this가 되며(왼쪽 코드 참고), &lt;i&gt;setTimeout&lt;/i&gt;과 같은 글로벌 함수 내부에서 호출하는 경우에는 this가 글로벌 스코프가 기본으로 가리키는 window를 가리킨다. 하지만&amp;nbsp;&lt;b&gt;&lt;i&gt;bind&lt;/i&gt;, &lt;i&gt;call&lt;/i&gt;, &lt;i&gt;apply&lt;/i&gt;를 사용하면 this가 객체를 가리키도록 동적 바인딩 할 수 있다.&lt;/b&gt;(오른쪽 코드 참고)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;610&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zJ8Hq/btrDQF4Er0H/aXYS7uPdm4uAU692bV5ymk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zJ8Hq/btrDQF4Er0H/aXYS7uPdm4uAU692bV5ymk/img.png&quot; data-alt=&quot;Bind 사&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zJ8Hq/btrDQF4Er0H/aXYS7uPdm4uAU692bV5ymk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzJ8Hq%2FbtrDQF4Er0H%2FaXYS7uPdm4uAU692bV5ymk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;438&quot; height=&quot;330&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;610&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Bind 사&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예제에서 글로벌 함수에서 객체의 내부 함수를 호출 했을 때, bind를 하지않는 경우 변수를 찾지 못해 undefined를 출력함을 볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;958&quot; data-origin-height=&quot;942&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSgAZE/btrDNUI13dE/8qRNjqWwtqAxe12hzzXfKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSgAZE/btrDNUI13dE/8qRNjqWwtqAxe12hzzXfKK/img.png&quot; data-alt=&quot;화살표 함수와 일반 함수의 this&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSgAZE/btrDNUI13dE/8qRNjqWwtqAxe12hzzXfKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSgAZE%2FbtrDNUI13dE%2F8qRNjqWwtqAxe12hzzXfKK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;423&quot; height=&quot;416&quot; data-origin-width=&quot;958&quot; data-origin-height=&quot;942&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;화살표 함수와 일반 함수의 this&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;화살표 함수의 This는 함수가 선언되는 곳의 부모 컨텍스트를 가리킨다. 또한, bind와 같은 동적 바인딩이 불가능 하다.&lt;/b&gt;&amp;nbsp;위의 예제를 통해 화살표 함수와 일반 함수의 차이를 이해할 수 있을 것이다. 화살표 함수 f1은 let o의 내부에 선언이 되어있고, let o의 부모 컨텍스트는 global이고 this가 가리키는 것이 된다. 반면 일반함수 f2는 호출하는 곳에 따라 this가 달라지며, 객체를 통해 호출 했기때문에 this는 객체 o 그 자체가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;952&quot; data-origin-height=&quot;826&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/syTTd/btrDRMa9FUY/1Ce005uoevEGKMWAG1BrDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/syTTd/btrDRMa9FUY/1Ce005uoevEGKMWAG1BrDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/syTTd/btrDRMa9FUY/1Ce005uoevEGKMWAG1BrDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsyTTd%2FbtrDRMa9FUY%2F1Ce005uoevEGKMWAG1BrDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;405&quot; height=&quot;351&quot; data-origin-width=&quot;952&quot; data-origin-height=&quot;826&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 다른 예제로 다시 설명하자면, 화살표 함수 f2는 method()내에 선언되어 있고 이 것의 부모 컨텍스트는 const o이다. 따라서 f2의 this는 const o를 가리킨다. 반면, f1()과 같은 일반적인 호출에서는 바인딩된 컨텍스트가 없으므로 default 값인 global을 가리킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체 내부의 this&lt;/h3&gt;
&lt;pre id=&quot;code_1673755069530&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const Something = function(element) {
  this.name = 'Something Good';
  this.handleEvent = function(event) {
    console.log(this.name); // 'Something Good'
    switch(event.type) {
      case 'click':
		...
        break;
      case 'dblclick':
		...
        break;
    }
  };

  element.addEventListener('click', this, false);
  element.addEventListener('dblclick', this, false);
  
  element.removeEventListener('click', this, false);
  element.removeEventListener('dblclick', this, false);
}
const s = new Something(document.body);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Class 혹은 객체에서 &lt;i&gt;this&lt;/i&gt;를 &lt;i&gt;addEventListener&lt;/i&gt;의 callback으로 주게되면 class내부의 &lt;i&gt;handleEvent&lt;/i&gt; 함수를 실행하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;혹은 &lt;i&gt;객체명[&quot;onclick&quot;]()&lt;/i&gt; 과 같이 호출할 수도 있다. &lt;i&gt;this.handleEvent&lt;/i&gt;로 호출하지 않도록 하자.&lt;/p&gt;</description>
      <category>React/JavaScript</category>
      <category>JavaScript</category>
      <category>this</category>
      <author>박유상의 개발블로그</author>
      <guid isPermaLink="true">https://muhly.tistory.com/152</guid>
      <comments>https://muhly.tistory.com/152#entry152comment</comments>
      <pubDate>Thu, 2 Jun 2022 23:05:49 +0900</pubDate>
    </item>
    <item>
      <title>[React] 다국어 변환 라이브러리 i18n</title>
      <link>https://muhly.tistory.com/151</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;웹 사이트에서 글로벌 서비스를 위해 여러 국가의 언어를 지원할 수 있도록 되도록 i18n 라이브러리를 사용해보자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동 번역이 되는 것은 아니고, 번역된 데이터가 담긴 JSON 파일을 프로젝트에 삽입 후, 국가 코드를 변경할 때마다 각 국가에 해당하는 JSON 파일을 읽어와 화면에 출력 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설치&lt;/h2&gt;
&lt;pre id=&quot;code_1654167281939&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install react-i18next i18next --save

yarn add react-i18next i18next&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;언어 파일&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1438&quot; data-origin-height=&quot;1270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/H6lX7/btrDRjmusRH/ZIyxUqMgBxnmZS4SuTekM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/H6lX7/btrDRjmusRH/ZIyxUqMgBxnmZS4SuTekM1/img.png&quot; data-alt=&quot;translation_ko.json&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/H6lX7/btrDRjmusRH/ZIyxUqMgBxnmZS4SuTekM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FH6lX7%2FbtrDRjmusRH%2FZIyxUqMgBxnmZS4SuTekM1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;495&quot; height=&quot;437&quot; data-origin-width=&quot;1438&quot; data-origin-height=&quot;1270&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;translation_ko.json&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 내에 다음과 같은 JSON 파일을 생성한다. JSX내에서 Key를 text로서 사용하면 국가 코드에 따라 Value를 출력한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;i18n 설정&lt;/h2&gt;
&lt;pre id=&quot;code_1654168205941&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import i18n from &quot;i18next&quot;;
import { initReactI18next } from &quot;react-i18next&quot;;

//JSON 파일 import
import translationKo from &quot;./translation.ko.json&quot;;
import translationEn from &quot;./translation.en.json&quot;;

const resource = {
//국가 코드와 JSON 파일 match
  ko: {
    translation: translationKo,
  },
  en: {
    translation: translationEn,
  },
};

i18n.use(initReactI18next).init({
  resources: resource,
  lng: &quot;en&quot;, //default 국가 코드
  debug: true,
  keySeparator: false,
  interpolation: { escapeValue: false },
});

//브라우저 DB에 기록된 언어가 있으면 해당 언어를 불러온다.
let language = localStorage.getItem(&quot;language&quot;);
if(language!==null)
i18n.changeLanguage(language);

//국가 코드를 변경하는 함수
export function changeLanguage() {
  i18n.changeLanguage(i18n.language === &quot;ko&quot; ? &quot;en&quot; : &quot;ko&quot;);
  //브라우저 DB에 기록
  localStorage.setItem(&quot;language&quot;, i18n.language);
}

export default i18n;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 설정과 국가 코드를 변경하는 함수를 담은 파일을 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;최상위에서 호출&lt;/h2&gt;
&lt;pre id=&quot;code_1654170125109&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import &quot;./Service/Translation/i18n&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최상위에서 해당 파일을 import 한다. import시 파일이 Read 되어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;useTranslation&lt;/h2&gt;
&lt;pre id=&quot;code_1654169402669&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { t, i18n } = useTranslation();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useTranslation을 다음과 같이 선언한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;현재 국가 코드 반환&lt;/h4&gt;
&lt;pre id=&quot;code_1654169484182&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;i18n.language&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;다국어 지원 텍스트 출력&lt;/h4&gt;
&lt;pre id=&quot;code_1654169572918&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;`${t('Blog')}` //JSON에 따라 '블로그'로 출력&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>React/React Tech</category>
      <category>I18N</category>
      <category>useTranslation</category>
      <author>박유상의 개발블로그</author>
      <guid isPermaLink="true">https://muhly.tistory.com/151</guid>
      <comments>https://muhly.tistory.com/151#entry151comment</comments>
      <pubDate>Thu, 2 Jun 2022 20:34:29 +0900</pubDate>
    </item>
    <item>
      <title>ICT 글로벌 인턴십 실리콘밸리 합격 후기</title>
      <link>https://muhly.tistory.com/150</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhUOax/btrC7ylJOb9/kRyA7nx6ZMCVbo1pIryWTK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhUOax/btrC7ylJOb9/kRyA7nx6ZMCVbo1pIryWTK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhUOax/btrC7ylJOb9/kRyA7nx6ZMCVbo1pIryWTK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhUOax%2FbtrC7ylJOb9%2FkRyA7nx6ZMCVbo1pIryWTK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;566&quot; height=&quot;801&quot; data-origin-width=&quot;724&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;합격&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 ICT 학점연계 프로젝트 글로벌 인턴십 프로그램을 통해 오는 7월부터 12월까지 실리콘밸리 음악 빅데이터 스타트업 Chartmertic에서 인턴 생활을 하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 프로그램을 지원하고자 하는 분들을 위해 경험과 함께 글을 남긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;ICT 학점연계 프로젝트 인턴십 글로벌 과정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 과정은 정부에서 국내외의 기업과 컴퓨터 관련 계열 학생의 인턴 매칭을 지원해주는 프로그램이다. 매 학기마다 열리며, 글로벌 과정의 경우 &lt;b&gt;학교에서 추천받은 학생&lt;/b&gt;만 지원 자격이 부여된다. 관심 있다면 학교에 먼저 문의해야 한다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선발된 학생은 상반기는 &lt;b&gt;3월부터 8월&lt;/b&gt;까지, 하반기는 &lt;b&gt;7월부터 12월&lt;/b&gt;까지 미국의 실리콘밸리에서 인턴십을 진행하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정부에서 항공료, 비자, 의료보험 등과 매월 150만 원을 지원해주며, 기업에서는 $1,700 이상 매월 지원해준다. &lt;s&gt;세전인데 어떻게 월세 내지..&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이번에는 가장 많이 지원해주는 회사가 $2,000이었지만, 작년에는 $2,700도 있었다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;지원 과정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우선 학교에서 추천 학생으로 선발되어야 한다.&lt;/b&gt; 각 학교마다 기준이 천차만별이다. 본인 학교의 경우는 지난 기수 까지는 학생 경력 점수를 반영해 추천 인원 제한인 3명만 선발해 추천해주었지만, 이번 기수부터 ICT 인턴십 측에서 각 학교당 추천 인원이 사라져 본인 학교에서는 원하는 모든 인원을 추천해주었다. 학생 경력 점수가 높지 않았던 나는 이번 기수에 바뀐 규정 덕에 지원할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후, &lt;b&gt;추천 학생 대상으로 기업 리스트가 주어진다.&lt;/b&gt; 약 5개에서 8개 정도의 회사가 리스트에 올라오게 된다. 인공지능/데이터, 웹, 모바일 포지션 순서대로 많이 요구하는 듯하다. &lt;b&gt;총 3개의 원하는 기업을 고른 후, 자기소개서와 포트폴리오를 영문으로 작성 후&lt;/b&gt; 제출한다. 약 1주일 정도가 주어진다. 본인은 미리 포트폴리오를 만들어 두어서 1주일 동안 자기소개서에 집중할 수 있었다. 무조건 포트폴리오 먼저 만들기!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;코딩 테스트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서류 합격 결과 발표 전 &lt;b&gt;HackerRank에서 코딩 테스트가 진행&lt;/b&gt;된다. 문제는 총 5문제로 3일 내에 연달아 6시간을 응시할 수 있다. 백준 기준 실버~골드 5 정도의 문제였던 것 같다. 사실, 코딩 테스트 결과는 절반 이상만 푼다면 서류 단계에서 큰 영향을 미치지는 않는 듯했고 면접에서 풀었던 코딩 테스트에 대해서는 전혀 물어보지 않았다. 부담 갖지 말고 하자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;서류 합격 후&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;약 1주일 정도의 면접 준비 기간이 주어진다. 면접은 스카이프로 진행되며 지난 후기들을 찾아보며 예상 질문을 추려냈었고, 일부 기업에서는 한국어와 영어를 혼용, 한 기업에서는 라이브 코딩 테스트를 진행 함을 알고 준비했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;면접&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접은 스카이프로 진행되며 4일 동안 오전 시간을 이용해 면접을 보게 된다. 이하는 내가 면접을 봤던 회사들의 간략한 면접 내용이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간은 각 면접 당 45분이며, 모든 회사가 45분을 꽉 채워서 면접을 봐주셨다.. ^^... 끝나고 바로 하루 종일 앓아누웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;E____ (교육 회사)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한국인 CEO 한 분과 한국인 기술 파트 한 분이 면접으로 참여하셨다. 면접 날짜의 첫 면접 타임이라 나의 교육 스타트업 경력을 좋게 봐주셨음이 틀림없다는 생각이 들었다. 편하게 임하려고 했지만 인생 첫 채용 면접이다 보니 많이 긴장해서 동문서답하고 영어를 많이 뚝딱거렸던 기억이 난다. 꼬리 질문을 많이 날리셔서 당황했던 기억이 남는다,,,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 영어로 진행된 면접&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;간단한 자기소개&lt;/li&gt;
&lt;li&gt;몇 학점이 남았는지? (인턴십 이후 정규직 채용을 고려하는 듯하였다.)&lt;/li&gt;
&lt;li&gt;왜 우리 회사에 지원했는지?&lt;/li&gt;
&lt;li&gt;자신이 좋아하는 것이 무엇인지?&lt;/li&gt;
&lt;li&gt;자신이 싫어하는 것이 무엇인지?&lt;/li&gt;
&lt;li&gt;어떤 과목을 가장 싫어하는지? (수학을 가장 싫어한다고 답했다. 그리고 E사의 수학 앱이 어릴 때 있었더라면 수포자가 되지 않았을 거라고 말씀드리니 너무 좋아하셨던 모습이 기억에 남는다)&lt;/li&gt;
&lt;li&gt;몰타에는 뭐하러 갔나요..?? (아무래도 영어를 뚝딱거리니 물어보셨던 것 같다... 흑흑)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기부터는 한국어로 해도 된다고 하셨다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가장 좋아하는 프로젝트는?&lt;/li&gt;
&lt;li&gt;프로젝트의 구조를 간단히 설명해보아라 (웹 포지션으로 지원했었기 때문에 웹 프로젝트를 설명했지만, 나의 교육 스타트 업 경험 때문에 서류를 통과해주신 거라고, 여기에 대해 설명해달라고 하셨다.)&lt;/li&gt;
&lt;li&gt;9개월 만에 30만 유저는 어떻게 달성한 것인지?&lt;/li&gt;
&lt;li&gt;어떤 계기로 교육에 흥미를 갖고 스타트 업을 시작하게 된 것인지?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고, 자기 PR을 할 수 있는 시간을 주셨고, 준비했던 마무리 멘트를 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;질문 시간에는 해당 회사에서 무엇을 배울 수 있는지, 어떤 일을 하게 될지, 웹 분야 말고도 일을 해볼 수 있는지 등을 여쭈어 보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막에는 이메일을 주시면서 궁금한 게 있으면 나중에 연락 달라고 하셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Chartmertic (음악 빅 데이터)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 최종 합격해서 6개월 간 인턴을 하게 될 회사이다. 외국인 면접관 한 분께서 참여하셨다. 들어오셔서 영어로 회사에 대해 소개해주셨는데 리스닝이 약해서 모두 알아듣진 못했다.. 매우 매우 걱정된다. 해당 기업 인터뷰는 개인적인 질문 약간, 프로젝트에서 사용된 기술에 대한 질문, 그리고 사용하게 될 기술에 대한 질문이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 면접 내용&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;간단한 자기소개&lt;/li&gt;
&lt;li&gt;왜 우리를 선택했는지?&lt;/li&gt;
&lt;li&gt;Lingory(교육 스타트업)에서 어떤 기술을 사용했는지 기재가 안되어 있는데 기술에 대해 설명해달라.&lt;/li&gt;
&lt;li&gt;왜 ReactNative 대신에 Flutter를 채택했는지?&lt;/li&gt;
&lt;li&gt;본인이 생각하기에 ReactNative와 Flutter의 전망은? (구글 트렌드를 예로 들며 Flutter의 인기 상승률이 높다고 답했다)&lt;/li&gt;
&lt;li&gt;다른 기술들은 어떤 것을 할 줄 아는지? 회사에서 요구하는 기술들을 잘 알고 있는지? (Express, React 등)&lt;/li&gt;
&lt;li&gt;React로 진행했던 프로젝트(Bitfolio)에 대해 설명해달라.&lt;/li&gt;
&lt;li&gt;React의 상태 관리의 종류에 대해 설명해달라.&lt;/li&gt;
&lt;li&gt;Firebase로 NoSQL은 알고 있는 듯 하나, SQL에 대해 알고 있는지?&lt;/li&gt;
&lt;li&gt;SQL의 Join에 대해 설명해달라. (자세히는 모르고 종류만 알고 있다고 말씀드리니, 직접 영어로 답변해주셨다. &lt;s&gt;리스닝 공부하자..&lt;/s&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기술적인 질문 공세에 정신이 혼미했었다. 다행히 얼마 전 프로그래머스 코딩 테스트를 준비하면서 SQL을 풀어본 덕에 Join의 종류라도 답할 수 있었고, 이후 면접관님의 표정이 좋아지시면서 나중에 회사에 들어오면 천천히 배우면 된다고 격려해주셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후, 마찬가지로 질문 시간이 주어졌다. 시간이 꽤 많이 남아 별 질문을 다했다. 내가 현재 출시된 프로덕트의 모바일 버전이 무엇으로 개발되었는지 물어보았는데 ReactNative라고 하셨다. 왜 Flutter를 사용하지 않았는지 물어보니 날카로운 질문이라고 흐뭇한 표정을 지으시며 React 개발자들이 있기 때문이라고 대답해주셨다. 그리고 내가 근무하면서 Flutter로 개발하고 싶다고 말씀드리니 열정을 보여줘서 감사하다고 말씀하셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;B___ R_______ (인공지능 로봇)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매 회 해당 인턴십에 참가하는 기업으로, 가장 많은 인원을 뽑고 면접이 라이브 코딩 테스트로 진행한다는 사실.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역시 외국인 면접관 한 분께서 참여하셨고 간단한 자기소개 및 장점 질문 이후 나도 동일하게 라이브 코딩 테스트로 면접을 진행했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;링크를 보내주시고 라이브 코딩 플랫폼에서 진행되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 BFS 문제로 난이도는 백준 기준 실버 2 정도의 문제였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라이브 코딩 테스트 팁들을 많이 찾아보았는데, 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모호한 질문의 경우는 반드시 되물어보아라.&lt;/li&gt;
&lt;li&gt;로직을 우선 설명 후, 코드를 작성 함과 동시에 어떤 역할을 하는 코드인지 설명하라.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 예전에 풀어본 것과 똑같은 문제로 술술 풀어나갈 수 있었지만 영어 설명을 굉장히 뚝딱거린 탓인지,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제를 모두 풀고 난 후 다시 한번 정리 설명하겠습니다!라고 했더니 문제 풀면서 충분히 설명해서 이해했다고 하셨다 ^^... (정말 충분했던 걸까 뚝딱거리는 영어를 듣기 힘드셨던 걸까..) 중간에 변수 명과 비교 연산자의 방향을 잘못 쓴 탓에 한참 잘못된 결과가 나왔었는데 적극적으로 힌트를 주시고 도와주셔서 문제를 해결할 수 있었다. 약 15분 정도의 시간이 남았고, 마찬가지로 질문 시간을 가졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에 라이브 코딩 테스트가 면접인 기업들이 꽤 많은데, 많이 연습하고 다듬어야겠다고 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로, 해당 기업은 React를 사용한다는 말이 없지만, 면접에서 실제 프로덕트는 React로 개발되어 로봇의 크롬 OS 환경에 탑재되어 메인 프로그램으로 동작한다고 하셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;선택&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 결과 발표가 24일이었다. 참가 학생은 면접을 본 기업을 우선순위를 매겨 제출하고 우선순위로 합격한 기업 한 곳만 알려주게 되어있다. 감사하게도 첫 번째로 면접을 보았던 교육 기업 E____에서 이메일로 먼저 연락을 주셨다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2022-05-25 오후 9.53.08.png&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgrNj4/btrC7IBOAWi/fmGWyJt1dHybfC134q6MXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgrNj4/btrC7IBOAWi/fmGWyJt1dHybfC134q6MXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgrNj4/btrC7IBOAWi/fmGWyJt1dHybfC134q6MXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgrNj4%2FbtrC7IBOAWi%2FfmGWyJt1dHybfC134q6MXk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;591&quot; height=&quot;261&quot; data-filename=&quot;스크린샷 2022-05-25 오후 9.53.08.png&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접도 너무 즐거웠었기 때문에 이메일을 이렇게 보내주심이 더 감동적이었다. 이 기업의 프로덕트를 사용해보면서 교육에 대한 진심이 느껴져서 눈물을 흘린 적도 있었다.(정말로..) 그리고 함께 일해보고 싶다는 생각으로 최선을 다했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 면접을 마치고 그리고, 위의 이메일을 받고 정말 많은 고민을 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교육 스타트업을 하며 에듀 테크에 대한 꿈이 있었고, 4차 산업혁명의 기반이 될 수 있는 빅데이터를 배워보고 싶은 욕구도 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;E사 이외에는 합격 이메일을 받은 게 없었지만, 우선순위를 매길 수 있었기 때문에 빅데이터를 배우고 싶은 욕구를 더 우선순위로 두기로 했다. 그리고 락밴드를 하며 음악에 푹 빠져 지냈던 때가 있었기에 음악을 더 가까이하고 싶기도 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 중요한 이유는 확실하게 웹 개발을 하는 직무를 맡고 싶었었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1328&quot; data-origin-height=&quot;582&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lkFfR/btrC7JHuvD3/EkWrugwFzTCUh36AX13WW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lkFfR/btrC7JHuvD3/EkWrugwFzTCUh36AX13WW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lkFfR/btrC7JHuvD3/EkWrugwFzTCUh36AX13WW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlkFfR%2FbtrC7JHuvD3%2FEkWrugwFzTCUh36AX13WW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;598&quot; height=&quot;262&quot; data-origin-width=&quot;1328&quot; data-origin-height=&quot;582&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 Chartmetric에 합격했다!&lt;/p&gt;</description>
      <category>Who am I/Reminiscence</category>
      <category>Chartmetric</category>
      <category>ICT글로벌</category>
      <category>ICT학점인정연계프로젝트</category>
      <category>실리콘밸리</category>
      <author>박유상의 개발블로그</author>
      <guid isPermaLink="true">https://muhly.tistory.com/150</guid>
      <comments>https://muhly.tistory.com/150#entry150comment</comments>
      <pubDate>Wed, 25 May 2022 22:26:12 +0900</pubDate>
    </item>
    <item>
      <title>[Express] Node.JS Express 시작하기</title>
      <link>https://muhly.tistory.com/149</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9cY65/btrBsYLVjJQ/44KCsHtbTlklUHloSOI471/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9cY65/btrBsYLVjJQ/44KCsHtbTlklUHloSOI471/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9cY65/btrBsYLVjJQ/44KCsHtbTlklUHloSOI471/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9cY65%2FbtrBsYLVjJQ%2F44KCsHtbTlklUHloSOI471%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;503&quot; height=&quot;211&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;420&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.JS와 Express는 항상 함께 언급되며, NodeJS는 React를 사용할 때에도 출현한다. 도대체 무엇일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Node.JS&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.JS는 웹의 발전에 따라 등장했는데, 단 방향 통신 위주였던 웹 1.0에서 사용자와 상호작용을 하는 웹 2.0이 등장했다. 이에 따라 구글에서는 고성능의 자바스크립트 동작을 위해 크롬 웹 브라우저를 위한 V8이라는 자바스크립트 엔진을 개발했다. 오픈소스인 V8를 활용해 자바스크립트를 웹뿐만 아니라 어느 환경에서나 사용할 수 있도록 개발된 실행기가 Node.JS이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.JS의 등장에 따라 자바스크립트로 다양한 역할을 할 수 있게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;크로스 플랫폼 실행&lt;/li&gt;
&lt;li&gt;제한 없는 동작&lt;/li&gt;
&lt;li&gt;다양한 어플리케이션 실행 가능&lt;/li&gt;
&lt;li&gt;Front-End(React), Back-End(Express), Mobile(ReactNative), Desktop(Electron), MachineLearning(Brain)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흔히 알고 있는 RN 뿐만 아니라 Slack과 Discord에 사용된 Electron, 심지어는 머신러닝까지 가능하게 해주는 런타임 실행기이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로, Babel이라는 컴파일러 도구를 내장하고 있어 React에서 사용하는 JSX 문법을 사용할 수 있게 해 주고 구 웹브라우저를 지원해주며, 내장된 Webpack 도구는 SPA(Single Page Application)의 개발에서 생산되는 정적 파일들을 번들링 하게 도와준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Node.JS 특징&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.JS 특징은 3가지로 간단하게 설명할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;싱글 쓰레드&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쓰레드란 명령을 실행하는 단위로, 한 번에 하나의 동작만 수행 가능하다. 리소스 관리에 효율적이지만 작업의 효율이 떨어진다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;비동기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동작을 실행한 후 완료까지 기다리지 않고 다른 동작이 실행된다. 싱글 쓰레드의 작업 효율이 떨어지는 단점을 수동적으로 보완할 수 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이벤트 기반&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 동작의 완료를 처리하는 방법으로, 비동기 동작의 완료 시 미리 등록된 함수를 실행한다. 쉽게 말해 then과 같은 함수를 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Express&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Express는 웹 애플리케이션을 구축하는 NodeJS 기반 프레임워크이다. API 통신을 지원하며 간단하게 백엔드 서버를 구축할 수 있다. 자유도가 높지만 기본적으로 제공되는 CRUD 이외에 데이터베이스나 심지어 관리자 페이지까지도 직접 개발해야 한다. 커뮤니티가 크고 이미 많은 서비스에서 사용되고 검증된 프레임워크이기 때문에 사실 간편하게 입맛에 맞는 라이브러리를 찾을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Express 구축&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 TypeScript Express를 구축해보고 API 서버를 로컬로 열어보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;패키지 설치&lt;/h4&gt;
&lt;pre id=&quot;code_1651852719801&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//터미널에 입력한다. TypeScript용으로 설치한다.
//cors 패키지는 외부 접근을 차단하는 cors 에러를 해제하기 위해 설치한다.
npm i @types/express @types/cors express cors ts-node typescript nodemon&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Heroku에 배포하기 위해 npm으로 설치해주자!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기본 설정 파일 생성&lt;/h4&gt;
&lt;pre id=&quot;code_1651852865526&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//프로젝트의 기본 이름, 설명 등을 입력받게 한다.
npm init -y

//TypeScript config 파일을 생성한다.
tsc --init

//Ts 파일을 생성한다. index.js와 같은 역할이다.
touch server.ts&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1651852963917&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//package.json에 다음을 추가한다.

  &quot;scripts&quot;: {
    &quot;start&quot;: &quot;ts-node server.ts&quot;, //JavaScript는 'node server.js'
    &quot;dev&quot;: &quot;nodemon -x ts-node server.ts&quot;
  },
  &quot;engines&quot;: {
    &quot;node&quot;: &quot;v14.16.1&quot;,
    &quot;npm&quot;: &quot;6.14.12&quot;
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;package.json에 다음과 같이 설정해주면 'npm start'를 입력했을 때 자동으로 'ts-node server.ts'로 변경되어 서버가 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;백엔드 구축하기&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;384&quot; data-origin-height=&quot;322&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9gd9g/btrBzUXbw7o/vvY8fM8g13nHzc28FVSVPK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9gd9g/btrBzUXbw7o/vvY8fM8g13nHzc28FVSVPK/img.png&quot; data-alt=&quot;.gitignore로 모듈을 제외해주자&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9gd9g/btrBzUXbw7o/vvY8fM8g13nHzc28FVSVPK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9gd9g%2FbtrBzUXbw7o%2FvvY8fM8g13nHzc28FVSVPK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;192&quot; height=&quot;161&quot; data-origin-width=&quot;384&quot; data-origin-height=&quot;322&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;.gitignore로 모듈을 제외해주자&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정을 모두 완료하면 다음과 같은 파일 구성이 된다. server.ts가 메인 코드를 실행하는 파일이 되며 내부에 다음과 같은 코드를 삽입해보자.&lt;/p&gt;
&lt;pre id=&quot;code_1651853581303&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//express를 import 한다. JavaScript에서는 'const express = require('express')'가 일반적이다.
import express, { Request, Response } from &quot;express&quot;;
const app = express();

//외부 접근시 발생하는 cors를 해제하기 위한 라이브러리이다.
const cors = require(&quot;cors&quot;);

//서버에 사용될 port 번호이다. 현재는 환경 변수 파일이 없으므로 3001이 된다.
const PORT = process.env.PORT || 3001;

//express에 cors 라이브러리를 삽입한다.
app.use(cors());



//GET API를 정의한다.
app.get(&quot;/&quot;, (req: Request, res: Response) =&amp;gt; {
  res.send(&quot;Server is running&quot;);
});

app.get(&quot;/user/1&quot;, (req: Request, res: Response) =&amp;gt; {
  res.json({
    id: 1,
    name: &quot;yusang&quot;,
    major: &quot;computer&quot;,
  });
});



//서버 가동 시 실행하는 동작이다.
app.listen(PORT, () =&amp;gt; console.log(&quot;server running..&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;실행&lt;/h4&gt;
&lt;pre id=&quot;code_1651853731471&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm start&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;210&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFjtHD/btrBsvpGda7/CCdD3k6CzKYzzVuD9KKO50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFjtHD/btrBsvpGda7/CCdD3k6CzKYzzVuD9KKO50/img.png&quot; data-alt=&quot;localhost:3001에서 서버를 확인할 수 있다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFjtHD/btrBsvpGda7/CCdD3k6CzKYzzVuD9KKO50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFjtHD%2FbtrBsvpGda7%2FCCdD3k6CzKYzzVuD9KKO50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;342&quot; height=&quot;128&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;210&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;localhost:3001에서 서버를 확인할 수 있다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;218&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQ4dD3/btrBr8Bhs0p/uUpbgCDF4MfjmIvc7pnPak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQ4dD3/btrBr8Bhs0p/uUpbgCDF4MfjmIvc7pnPak/img.png&quot; data-alt=&quot;GET으로 전달된 user/1 데이터이다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQ4dD3/btrBr8Bhs0p/uUpbgCDF4MfjmIvc7pnPak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQ4dD3%2FbtrBr8Bhs0p%2FuUpbgCDF4MfjmIvc7pnPak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;347&quot; height=&quot;109&quot; data-origin-width=&quot;694&quot; data-origin-height=&quot;218&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;GET으로 전달된 user/1 데이터이다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 Express는 간단하게 Restful API를 생성할 수 있고, fetch, axios 등으로 간단하게 프런트엔드와 통신할 수 있는 HTTP를 제공한다. 앞서 말한 것처럼 데이터베이스 등을 별도로 연결해야 하지만 필요에 맞게 NoSQL을 사용할 수도 있는 자유도가 있다.&lt;/p&gt;</description>
      <category>NodeJS/NodeJS Basic</category>
      <category>express</category>
      <category>node.js</category>
      <author>박유상의 개발블로그</author>
      <guid isPermaLink="true">https://muhly.tistory.com/149</guid>
      <comments>https://muhly.tistory.com/149#entry149comment</comments>
      <pubDate>Sat, 7 May 2022 01:21:16 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 호이스팅과 클로저</title>
      <link>https://muhly.tistory.com/148</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;클로저&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트에서 함수는 일급 객체(First Class Object)로 취급된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;일급 객체란? 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가리킨다. 변수에 할당할 수 있으며, 다른 함수를 인자로 전달받는다. 또, 다른 함수의 결과로 return 될 수 있다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1898&quot; data-origin-height=&quot;938&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uTxNZ/btrBjXNv0q9/kblbsxUKlXpztFEB5XKrr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uTxNZ/btrBjXNv0q9/kblbsxUKlXpztFEB5XKrr0/img.png&quot; data-alt=&quot;출처 엘리스SW트랙&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uTxNZ/btrBjXNv0q9/kblbsxUKlXpztFEB5XKrr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuTxNZ%2FbtrBjXNv0q9%2FkblbsxUKlXpztFEB5XKrr0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1898&quot; height=&quot;938&quot; data-origin-width=&quot;1898&quot; data-origin-height=&quot;938&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 엘리스SW트랙&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로저는 Factory 함수가 저장되는 공간이라고 할 수 있으며 일급 객체 성질을 이용한다. 선언된 createCard()를 객체 처럼 다룰 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 클로저를 생성시에 각각의 스코프가 생성되어, 내부 변수는 공유되지 않는다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Factory 함수란? 함수들을 객체의 형태로 return 하는 함수. 위의 코드의 createCard()도 Factory 함수이다.&lt;br /&gt;Class를 return 생성, return하는 경우도 있다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;호이스팅&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;var 변수와 function의 선언이 코드의 맨 위로 끌어올려지는 현상이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트에는 크게 var와 let 타입의 변수가 존재한다. var 타입이 영향을 받는 호이스팅이라는 개념이 일반적인 상황에서는 실수를 야기할 수 있는데, 이에 대한 대안으로 let 타입의 변수가 등장 하게 되었다. 대부분의 경우에서는 var보다 let 사용이 권장된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1651769335534&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(a); //undefined
console.log(b); //Uncaught ReferenceError : Cannot access 'b' before initialization

var a = &quot;안녕하세요&quot;;
let b = &quot;반갑습니다&quot;;

console.log(a); //&quot;안녕하세요&quot;
console.log(b); //&quot;반갑습니다&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 예제 코드처럼 var 타입은 선언부가 최상단으로 끌어올려지며 초기화가 이루어져 참조가 가능하지만 undefined을 가지고, let은 초기화가 발생하지 않아 참조가 불가능하다. 정의된 부분 아래에서는 모두 참조가 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1651770080602&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(plus(10, 15))	// 25

function plus(a, b) {
	return a + b
}

console.log(minus(15, 5)) // Cannot access 'minus' before initialization

const minus = (a, b) =&amp;gt; {
	return a - b;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Function 함수는 호이스팅이 일어남과 함께 생성 단계에서 함수 전체가 저장 되므로, 호출이 가능하다. 반면 화살표 함수는 호이스팅이 발생하지 않으며, const 타입도 마찬가지로 호이스팅이 발생하지 않는다. 따라서, 위의 예제처럼 초기화되지 않아 참조할 수 없다는 에러를 확인할 수 있다.&lt;/p&gt;</description>
      <category>React/JavaScript</category>
      <category>JavaScript</category>
      <category>클로저</category>
      <category>호이스팅</category>
      <author>박유상의 개발블로그</author>
      <guid isPermaLink="true">https://muhly.tistory.com/148</guid>
      <comments>https://muhly.tistory.com/148#entry148comment</comments>
      <pubDate>Fri, 6 May 2022 02:11:50 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 실행 Context와 Scope</title>
      <link>https://muhly.tistory.com/147</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 엔진이 어떻게 동작 하는지 알아보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실행 컨텍스트 (Execution Context)&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2148&quot; data-origin-height=&quot;1110&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/90JNu/btrBk7JBY9S/IK79DolUDqWPxqk8acoTtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/90JNu/btrBk7JBY9S/IK79DolUDqWPxqk8acoTtK/img.png&quot; data-alt=&quot;실행 컨텍스트 스택 (call stack) (출처 엘리스SW트랙)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/90JNu/btrBk7JBY9S/IK79DolUDqWPxqk8acoTtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F90JNu%2FbtrBk7JBY9S%2FIK79DolUDqWPxqk8acoTtK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;788&quot; height=&quot;408&quot; data-origin-width=&quot;2148&quot; data-origin-height=&quot;1110&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행 컨텍스트 스택 (call stack) (출처 엘리스SW트랙)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트 엔진은 &lt;b&gt;실행 컨텍스트&lt;/b&gt; 스택의 흐름에 따라 동작한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;실행 컨텍스트란? 코드의 흐름과 변수 따위 등 함수 동작에 필요한 환경 정보가 담긴 객체를 지칭한다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;994&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CO7id/btrBgEOljJf/5oRVFikE1bgOtNlipZOpn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CO7id/btrBgEOljJf/5oRVFikE1bgOtNlipZOpn1/img.png&quot; data-alt=&quot;실행 컨텍스트 (출처 엘리스SW트랙)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CO7id/btrBgEOljJf/5oRVFikE1bgOtNlipZOpn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCO7id%2FbtrBgEOljJf%2F5oRVFikE1bgOtNlipZOpn1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;350&quot; height=&quot;326&quot; data-origin-width=&quot;994&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행 컨텍스트 (출처 엘리스SW트랙)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;This&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;this는 기본적으로 window를 가리키고, console.log와 같은 함수는 window에 포함되어 있다. 프로그래밍에서 의도한 위치의 변수나 함수를 사용하기 위해 this를 적절하게 사용해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1654178840272&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[JavaScript] This 포인터 이해하기&quot; data-og-description=&quot;This 포인터 클래스 내에서 this.변수명 형식으로 변수를 참조하는 것을 보았을 것이다. 앞서 실행 컨텍스트에 this가 포함된 것을 볼 수 있다. this는 스코프 마다 달라질 수 있는데, 크게&amp;nbsp;일반 함수&quot; data-og-host=&quot;muhly.tistory.com&quot; data-og-source-url=&quot;https://muhly.tistory.com/152&quot; data-og-url=&quot;https://muhly.tistory.com/152&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cgpnGm/hyOCC3ADGK/KGZBK3QbEnqvzzDnN8wTJ1/img.png?width=800&amp;amp;height=364&amp;amp;face=0_0_800_364,https://scrap.kakaocdn.net/dn/brG0i8/hyOCIW15Fu/quvHUEoODwYfhHNhwZH860/img.png?width=800&amp;amp;height=364&amp;amp;face=0_0_800_364,https://scrap.kakaocdn.net/dn/Aq6IG/hyOCIW14Z0/HCEYsPJ94bCgHftCipuVO1/img.png?width=750&amp;amp;height=342&amp;amp;face=0_0_750_342&quot;&gt;&lt;a href=&quot;https://muhly.tistory.com/152&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://muhly.tistory.com/152&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cgpnGm/hyOCC3ADGK/KGZBK3QbEnqvzzDnN8wTJ1/img.png?width=800&amp;amp;height=364&amp;amp;face=0_0_800_364,https://scrap.kakaocdn.net/dn/brG0i8/hyOCIW15Fu/quvHUEoODwYfhHNhwZH860/img.png?width=800&amp;amp;height=364&amp;amp;face=0_0_800_364,https://scrap.kakaocdn.net/dn/Aq6IG/hyOCIW14Z0/HCEYsPJ94bCgHftCipuVO1/img.png?width=750&amp;amp;height=342&amp;amp;face=0_0_750_342');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[JavaScript] This 포인터 이해하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This 포인터 클래스 내에서 this.변수명 형식으로 변수를 참조하는 것을 보았을 것이다. 앞서 실행 컨텍스트에 this가 포함된 것을 볼 수 있다. this는 스코프 마다 달라질 수 있는데, 크게&amp;nbsp;일반 함수&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;muhly.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Variable Object&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스코프(실행되는 환경 혹은 범위)에 있는 변수들을 담고 있다. 스코프가 존재하지 않는다면 변수 명이 같은 변수가 2개 이상 존재할 때 충돌을 일으킬 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Scope Chain&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에 연속적으로 실행되어야 할 동작을 담고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;동작 흐름&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 컨텍스트 스택이 만들어지고 실행되는 과정은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;자바스크립트 엔진이 코드의 유무와 관련 없이 &lt;b&gt;전역&amp;nbsp;실행 컨텍스트&lt;/b&gt;를 생성한다.&lt;/li&gt;
&lt;li&gt;함수가 호출되게 될 때, 함수의 환경 정보들을 모아&amp;nbsp;&lt;b&gt;실행 컨텍스트&lt;/b&gt;를 생성, 스택에 Push한다.&lt;/li&gt;
&lt;li&gt;맨 마지막으로 실행된 print 함수(예시 참고)의 &lt;b&gt;실행 컨텍스트&lt;/b&gt;는 변수 v를 가지고 있고, 해당 &lt;b&gt;실행 컨텍스트&lt;/b&gt;에서만 사용된다.&lt;/li&gt;
&lt;li&gt;print 함수가 생성할 다음&amp;nbsp;&lt;b&gt;실행 컨텍스트&lt;/b&gt;가 없으므로 print 함수를 실행하고, 끝나면 스택에서 Pop한다.&lt;/li&gt;
&lt;li&gt;스코프 체인을 따라 스택이 순차 실행된다. 모두 실행이 완료되면 &lt;b&gt;실행 컨텍스트&lt;/b&gt;로 돌아온다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실행 컨텍스트 생성 과정&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;생성 단계에서 엔진이 변수 선언을 읽는다. 함수 선언문, 함수 표현식, 변수 등을 읽어 실행 컨텍스트에 저장한다. 변수는 실행 컨텍스트의 렉시컬 환경 &lt;i&gt;Lexical Environment&lt;/i&gt;을 구성하고 함수 전체가 기록되며 이외의 값은 기록되지 않는다.&lt;/li&gt;
&lt;li&gt;실행 단계에서 변수 값을 할당한다. 변수에 값을 할당하는 구문을 만나면 실행 컨텍스트에 값을 저장한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lexical Environment&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렉시컬 환경은 스코프의 변수와 함수를 매개변수로 저장하는 객체이다. 코드가 실행 되면서 참조가 필요한 변수 값이 있을 때, 이 객체에서 식별자 이름을 Key로 찾는다. 함수의 고유한 영역을 구성하는 환경이라고 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1654179521669&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function print(v) {
	let id = 'a5vf32s';
    console.log(`${id} is running : ${v}`);
}

print()

//Lexical Environment's record
{v: undefined, a: 'a5vf32s' };&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Lexical Scope&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트는 렉시컬 스코프를 따르는데 함수 스코프를 생성될 때 어디서 호출 되었는지에 따르는 것이 아닌, 어디서 생성 되었는지를 따르는 것이다. 정적 스코프(Static scope)라고도 부른다. 렉시컬 환경이 함수의 고유한 영역을 구성하고, 이러한 특성을 따르는 것이다.&lt;/p&gt;
&lt;pre id=&quot;code_1651767645132&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var value = 5;

function first() {
  var value = 10;
  second();
}

function second() {
  console.log(value);
}

first(); // 5
second(); // 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드는 first() 내에 선언된 value는 second() 스코프의 value가 되지 않음을 보여주고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>React/JavaScript</category>
      <category>execution context</category>
      <category>JavaScript</category>
      <category>lexical</category>
      <category>scope</category>
      <author>박유상의 개발블로그</author>
      <guid isPermaLink="true">https://muhly.tistory.com/147</guid>
      <comments>https://muhly.tistory.com/147#entry147comment</comments>
      <pubDate>Fri, 6 May 2022 00:48:33 +0900</pubDate>
    </item>
  </channel>
</rss>