<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Oagree</title>
    <link>https://oagree0123.tistory.com/</link>
    <description>만드는 것을 좋아하는 프론트엔드 개발자</description>
    <language>ko</language>
    <pubDate>Sat, 30 May 2026 16:14:55 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>oagree0123</managingEditor>
    <item>
      <title>React 상태가 변경되어도 리렌더링되지 않는 이유와 해결법</title>
      <link>https://oagree0123.tistory.com/entry/React-%EC%83%81%ED%83%9C%EA%B0%80-%EB%B3%80%EA%B2%BD%EB%90%98%EC%96%B4%EB%8F%84-%EB%A6%AC%EB%A0%8C%EB%8D%94%EB%A7%81%EB%90%98%EC%A7%80-%EC%95%8A%EB%8A%94-%EC%9D%B4%EC%9C%A0%EC%99%80-%ED%95%B4%EA%B2%B0%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;React에서 상태를 바꿨는데 화면이 바뀌지 않는 이유 &amp;ndash; 자료형과 불변성의 이해&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 상태를 바꿔도 리렌더링되지 않는 상황&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React에서 가장 기본적인 원칙 중 하나는 상태를 변경하면 컴포넌트가 다시 렌더링된다는 것이다. 그러나 상태를 분명히 바꿔서 setState를 호출했는데도 화면이 전혀 변하지 않는 경우가 있다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const [user, setUser] = useState({ name: '길동' });

// 잘못된 방법
user.name = '지민';
setUser(user); // 리렌더링되지 않음!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자의 이름을 바꿔서 setUser를 호출했지만, 화면에는 기존 값이 그대로 남아 있다. 디버그를 해보면 상태는 분명 변경되었는데, React는 아무런 반응도 하지 않는다. 어떤 오류도, 로그도 없다. 하지만 이건 React가 잘못된 것이 아니라, 의도적으로 리렌더링을 생략한 경우다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 리렌더링이 발생하지 않은 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React는 상태가 변경되었는지를 판단할 때, 이전 상태와 새로운 상태를 비교한다. 이 비교에서 두 값이 같은 참조(메모리 주소)를 가지고 있을 경우 변경되지 않은 것으로 간주한다.&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;// React 내부적으로 이런 식으로 비교
if (이전상태 === 새로운상태) {
  // 참조가 같음 &amp;rarr; 상태 변경 없다고 간주 &amp;rarr; 리렌더링 생략
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞서 제시한 예시처럼 객체의 내부 속성만 변경한 경우, 객체의 참조는 동일하므로 React는 &quot;변경 없음&quot;으로 판단한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. JavaScript 자료형과 근본적 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제는 결국 JavaScript의 자료형 특성과 메모리 구조에서 시작된다. JavaScript에서는 모든 값이 두 가지 중 하나로 나누어진다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;원시값(Primitive)&lt;/b&gt;: number, string, boolean, null, undefined, symbol, bigint 등&lt;/li&gt;
&lt;li&gt;&lt;b&gt;참조값(Reference)&lt;/b&gt;: object, array, function 등&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;원시값은 본래 불변성을 가진다&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원시값은 그 자체로 &lt;b&gt;불변(immutable)&lt;/b&gt; 특성을 가진다. 한 번 생성된 값은 내부 상태가 변경되지 않으며, 변수에 다른 원시값을 할당한다는 것은 &lt;b&gt;새로운 값을 가리키는 것&lt;/b&gt;일 뿐, 기존 값을 수정하는 것이 아니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;let a = 'hello';
let b = a;
b = 'world';
console.log(a); // 'hello'
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;값 자체가 복사되기 때문에 a와 b는 전혀 다른 값을 가리킨다.&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;b&gt;메모리 주소&lt;/b&gt;가 들어간다. 복사하면 값을 복사하는 것이 아니라 같은 주소를 공유하게 된다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;const obj1 = { name: '길동' };
const obj2 = obj1;
obj2.name = '지민';

console.log(obj1.name); // '지민'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 참조값은 **내부 속성이 변경될 수 있는 구조(mutable)**를 가지며, 개발자가 직접 불변성을 지키지 않으면 예상과 다른 일이 생긴다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 불변성과 상태 업데이트 방식&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하려면 상태를 &lt;b&gt;불변하게(immutable)&lt;/b&gt; 다룰 필요가 있다. 기존 객체를 직접 수정하지 않고, 필요한 부분만 새로 복사하여 &lt;b&gt;새 객체로 교체&lt;/b&gt;해야 한다.&lt;/p&gt;
&lt;pre class=&quot;pf&quot;&gt;&lt;code&gt;// 객체 상태 업데이트
setUser({
  ...user,
  name: '지민',
});

// 중첩된 객체 상태 업데이트
setState({
  ...state,
  user: {
    ...state.user,
    name: '지민',
  },
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 하면 user 객체가 새로 생성되면서 참조값이 달라진다. React가 이 변화를 감지해서 리렌더링한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;배열 상태에서도 동일한 원칙 적용&lt;/h4&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;// 잘못된 방법
items.push(newItem);
setItems(items);

// 올바른 방법
setItems([...items, newItem]);

// 항목 제거
setItems(items.filter(item =&amp;gt; item.id !== targetId));
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;불변성이 깊은 복사를 무조건 하라는 건 아니다. React 입장에서는 &lt;b&gt;참조만 바뀌면 된다&lt;/b&gt;.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정리하기&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;React는 상태 변경을 감지할 때 참조 비교를 사용하며, 객체의 내부만 변경하고 참조가 같으면 변경을 감지하지 못한다.&lt;/li&gt;
&lt;li&gt;JavaScript에서 &lt;b&gt;원시값은 불변&lt;/b&gt;, &lt;b&gt;참조값은 내부 속성이 변경 가능한 구조&lt;/b&gt;로 구분된다.&lt;/li&gt;
&lt;li&gt;상태 업데이트 시 기존 객체를 수정하지 말고, 필요한 부분만 복사하여 새 객체로 만들어야 한다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>React</category>
      <category>react</category>
      <category>불변성</category>
      <category>자료형</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/104</guid>
      <comments>https://oagree0123.tistory.com/entry/React-%EC%83%81%ED%83%9C%EA%B0%80-%EB%B3%80%EA%B2%BD%EB%90%98%EC%96%B4%EB%8F%84-%EB%A6%AC%EB%A0%8C%EB%8D%94%EB%A7%81%EB%90%98%EC%A7%80-%EC%95%8A%EB%8A%94-%EC%9D%B4%EC%9C%A0%EC%99%80-%ED%95%B4%EA%B2%B0%EB%B2%95#entry104comment</comments>
      <pubDate>Tue, 27 May 2025 10:12:18 +0900</pubDate>
    </item>
    <item>
      <title>Next.js Docker 최적화 전략 : 멀티스테이지 빌드와 standalone 모드</title>
      <link>https://oagree0123.tistory.com/entry/Nextjs-Docker-%EC%B5%9C%EC%A0%81%ED%99%94-%EC%A0%84%EB%9E%B5-%E2%80%93-%EB%A9%80%ED%8B%B0%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80-%EB%B9%8C%EB%93%9C%EC%99%80-standalone-%EB%AA%A8%EB%93%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js&amp;nbsp;프로젝트는&amp;nbsp;로컬에서는&amp;nbsp;잘&amp;nbsp;작동하지만,&amp;nbsp;&amp;nbsp;&lt;br /&gt;Docker로&amp;nbsp;운영&amp;nbsp;환경에&amp;nbsp;배포하는&amp;nbsp;순간&amp;nbsp;전혀&amp;nbsp;다른&amp;nbsp;문제가&amp;nbsp;발생한다.&lt;br /&gt;&lt;br /&gt;-&amp;nbsp;빌드&amp;nbsp;결과물과&amp;nbsp;전체&amp;nbsp;소스를&amp;nbsp;모두&amp;nbsp;포함해&amp;nbsp;이미지&amp;nbsp;용량이&amp;nbsp;1GB를&amp;nbsp;넘고&amp;nbsp;&amp;nbsp;&lt;br /&gt;-&amp;nbsp;의존성은&amp;nbsp;바뀌지&amp;nbsp;않았는데도&amp;nbsp;매번&amp;nbsp;설치부터&amp;nbsp;다시&amp;nbsp;하게&amp;nbsp;되고&amp;nbsp;&amp;nbsp;&lt;br /&gt;-&amp;nbsp;빌드&amp;nbsp;시간과&amp;nbsp;배포&amp;nbsp;속도는&amp;nbsp;점점&amp;nbsp;길어지며&amp;nbsp;&amp;nbsp;&lt;br /&gt;-&amp;nbsp;실행&amp;nbsp;구조가&amp;nbsp;복잡해져&amp;nbsp;운영&amp;nbsp;환경에서&amp;nbsp;디버깅이나&amp;nbsp;관리가&amp;nbsp;번거로워진다&lt;br /&gt;&lt;br /&gt;단순히&amp;nbsp;&amp;ldquo;실행되는&amp;nbsp;Docker&amp;nbsp;이미지&amp;rdquo;를&amp;nbsp;만드는&amp;nbsp;것과&amp;nbsp;&amp;nbsp;&lt;br /&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;br /&gt;내가 직접 사용하고 있는 &lt;b&gt;두 가지 최적화 전략&lt;/b&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;b&gt;멀티스테이지 빌드 (Multi-stage Build)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Next.js standalone 모드&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두 가지를 함께 적용하면&lt;br /&gt;Docker 이미지 용량을 1/4로 줄이고, 빌드 시간과 배포 속도까지 개선할 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 멀티스테이지 구성과 최적화 효과&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티스테이지 빌드는 Dockerfile을 단계별로 분리해, 실행에 필요한 파일만 최종 이미지에 포함시키는 방식이다.&lt;br /&gt;Next.js처럼 빌드와 실행 환경이 명확히 구분되는 프로젝트에서 특히 유용하다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1단계: Base 스테이지&lt;/h3&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;FROM node:18-alpine AS base
&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;Alpine 이미지를 사용해 가능한 한 가벼운 Node.js 환경을 구성한다.&lt;/li&gt;
&lt;li&gt;모든 스테이지에서 이 이미지를 공유하면, Docker 캐시 효율이 향상된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2단계: deps 스테이지 (의존성 설치)&lt;/h3&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json package-lock.json* ./
RUN npm ci
&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;의존성 설치를 별도의 스테이지로 분리하면, 이후 단계에서 소스 코드가 변경되어도 Docker는 이 레이어를 캐시로 재사용한다.&lt;/li&gt;
&lt;li&gt;COPY package*.json &amp;rarr; RUN npm ci 순서를 유지하면 캐시가 효율적으로 적용되고, 전체 빌드 속도가 빨라진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3단계: builder 스테이지 (앱 빌드)&lt;/h3&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
&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;소스 코드와 의존성을 조합해 .next/ 디렉토리에 빌드 결과를 생성한다.&lt;/li&gt;
&lt;li&gt;COPY . .은 가장 마지막에 위치시켜 소스 변경 시 캐시 무효화를 최소화한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4단계: runner 스테이지 (standalone 미적용 기준)&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;FROM base AS runner
WORKDIR /app
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules

EXPOSE 3000
CMD [&quot;npm&quot;, &quot;start&quot;]&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;/li&gt;
&lt;li&gt;standalone 모드를 적용하지 않은 경우에는 .next, node_modules, public, package.json이 모두 필요하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;unoptimized vs. multistage&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전체 프로젝트를 포함한 Dockerfile은 이미지 용량이 1GB 이상까지 커질 수 있다.&lt;/li&gt;
&lt;li&gt;멀티스테이지 빌드를 적용하면 실행에 필요한 파일만 포함되어 약 600MB가 줄어든 것을 볼 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-14 오후 3.02.26.png&quot; data-origin-width=&quot;948&quot; data-origin-height=&quot;100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dZo1pP/btsNYUXMgO2/KoK9y1IYtZdk9WEhnSlUq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dZo1pP/btsNYUXMgO2/KoK9y1IYtZdk9WEhnSlUq1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dZo1pP/btsNYUXMgO2/KoK9y1IYtZdk9WEhnSlUq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdZo1pP%2FbtsNYUXMgO2%2FKoK9y1IYtZdk9WEhnSlUq1%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;948&quot; height=&quot;100&quot; data-filename=&quot;스크린샷 2025-05-14 오후 3.02.26.png&quot; data-origin-width=&quot;948&quot; data-origin-height=&quot;100&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-14 오후 3.02.59.png&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;88&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tS5Yo/btsNXnmCWNK/jSRfxu3gS7KwmDIXDXITKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tS5Yo/btsNXnmCWNK/jSRfxu3gS7KwmDIXDXITKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tS5Yo/btsNXnmCWNK/jSRfxu3gS7KwmDIXDXITKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtS5Yo%2FbtsNXnmCWNK%2FjSRfxu3gS7KwmDIXDXITKk%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;946&quot; height=&quot;88&quot; data-filename=&quot;스크린샷 2025-05-14 오후 3.02.59.png&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;88&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. Next.js standalone 모드&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;standalone 모드란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js에서 output: 'standalone'을 설정하면, 실행에 필요한 서버 코드와 의존성만 자동으로 .next/standalone에 추출된다.&lt;br /&gt;이 구조는 단일 실행 파일처럼 동작하며, 복잡한 디렉토리 복사 없이 실행 가능하다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;설정 방법&lt;/h3&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;// next.config.js
const nextConfig = {
  output: 'standalone',
};
module.exports = nextConfig;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실행 이미지 구성 방식 (standalone 적용 시)&lt;/h3&gt;
&lt;pre class=&quot;oxygene&quot;&gt;&lt;code&gt;COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
&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;/li&gt;
&lt;li&gt;복사해야 할 파일도 줄어들어 배포 구성이 간단해진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;standalone 모드의 장점&lt;/h3&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;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;multistage vs. standalone&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;멀티스테이지만 적용한 경우에도 node_modules 등이 포함되어 이미지가 다소 크다.&lt;/li&gt;
&lt;li&gt;standalone을 적용하면 실행 파일만 남아 이미지의 사이즈가 최적화된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-14 오후 3.02.59.png&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;88&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bx5RpF/btsNYhlBSeN/z40CZ5DYScATAnZq6fPk2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bx5RpF/btsNYhlBSeN/z40CZ5DYScATAnZq6fPk2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bx5RpF/btsNYhlBSeN/z40CZ5DYScATAnZq6fPk2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbx5RpF%2FbtsNYhlBSeN%2Fz40CZ5DYScATAnZq6fPk2k%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;946&quot; height=&quot;88&quot; data-filename=&quot;스크린샷 2025-05-14 오후 3.02.59.png&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;88&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-14 오후 3.03.28.png&quot; data-origin-width=&quot;947&quot; data-origin-height=&quot;90&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8FL5A/btsNWTlPxpO/h5j5XGKXsckmS9bvqs3lu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8FL5A/btsNWTlPxpO/h5j5XGKXsckmS9bvqs3lu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8FL5A/btsNWTlPxpO/h5j5XGKXsckmS9bvqs3lu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8FL5A%2FbtsNWTlPxpO%2Fh5j5XGKXsckmS9bvqs3lu1%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;947&quot; height=&quot;90&quot; data-filename=&quot;스크린샷 2025-05-14 오후 3.03.28.png&quot; data-origin-width=&quot;947&quot; data-origin-height=&quot;90&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티스테이지 빌드는 실행에 꼭 필요한 파일만 최종 이미지에 포함시켜 용량을 줄이고, Docker 캐시를 적극 활용해 빌드 속도를 개선한다.&lt;br /&gt;여기에 standalone 모드를 적용하면 복잡한 디렉토리 구성 없이 단일 실행 구조만으로도 앱을 운영할 수 있게 된다.&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;특히 output: 'standalone' 설정만으로 실행에 필요한 서버 코드와 의존성이 자동으로 추출되기 때문에, 이후 배포도 훨씬 간단해진다.&lt;/p&gt;</description>
      <category>React</category>
      <category>docker</category>
      <category>Next.js</category>
      <category>react</category>
      <category>Standalone</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/103</guid>
      <comments>https://oagree0123.tistory.com/entry/Nextjs-Docker-%EC%B5%9C%EC%A0%81%ED%99%94-%EC%A0%84%EB%9E%B5-%E2%80%93-%EB%A9%80%ED%8B%B0%EC%8A%A4%ED%85%8C%EC%9D%B4%EC%A7%80-%EB%B9%8C%EB%93%9C%EC%99%80-standalone-%EB%AA%A8%EB%93%9C#entry103comment</comments>
      <pubDate>Thu, 15 May 2025 10:50:47 +0900</pubDate>
    </item>
    <item>
      <title>Next.js standalone 배포 &amp;quot;sharp missing in production&amp;quot; 에러 해결하기</title>
      <link>https://oagree0123.tistory.com/entry/Nextjs-standalone-%EB%B0%B0%ED%8F%AC-sharp-missing-in-production-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js의 next/image 컴포넌트는 이미지 최적화를 위해 서버 측에서 sharp 모듈을 사용합니다. 하지만 Docker 기반의 production 환경에서는 종종 아래와 같은 오류가 발생합니다.&lt;/p&gt;
&lt;pre class=&quot;subunit&quot;&gt;&lt;code&gt;Error: 'sharp' is required to be installed in standalone mode for the image optimization to function correctly.
&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;개발 환경에서는 멀쩡히 동작하던 기능이 운영 환경에서 갑자기 실패하는 이유는 무엇일까요? 이 글에서는 해당 오류의 원인과 해결 방법을 명확히 정리해 봅니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 개발 환경에서는 왜 문제가 없을까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 중에는 sharp와 관련된 문제가 드러나지 않는 경우가 대부분입니다. 그 이유는 아래와 같습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1) 개발 환경은 glibc 기반&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 로컬 개발 환경(macOS, Ubuntu 등)은 glibc 기반입니다. 이 환경에서는 npm install 시 sharp가 자동으로 현재 시스템에 맞는 바이너리를 설치하고, 문제 없이 작동합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) sharp가 없어도 fallback 가능&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 sharp가 설치되어 있지 않거나, 설치에 실패한 경우에도 Next.js는 자동으로 squoosh라는 WebAssembly 기반 이미지 최적화 도구를 fallback으로 사용합니다. 이 도구는 설치가 간편하고 플랫폼 제약이 없어, 개발 환경에서는 큰 문제 없이 작동하게 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3) 그래서 문제를 인지하지 못함&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 sharp가 정상 작동하거나 squoosh로 대체되기 때문에, 개발 중에는 이미지 최적화 기능이 잘 작동하는 것처럼 보입니다. 실제로는 fallback이 발생했음에도 이를 인지하지 못한 채 배포까지 진행하게 되는 경우가 많습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 운영 환경에서는 왜 오류가 발생할까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js를 production에 배포할 때는 보통 다음과 같은 구성이 사용됩니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Docker + node:alpine 기반 이미지&lt;/li&gt;
&lt;li&gt;Next.js standalone 모드 빌드&lt;/li&gt;
&lt;li&gt;sharp 모듈 포함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 환경에서는 sharp가 아래와 같은 이유로 실행에 실패할 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1) Alpine 리눅스는 glibc가 아니다&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Alpine은 이미지 크기를 줄이기 위해 musl libc를 사용합니다. 반면, sharp는 기본적으로 glibc 기반 환경에서 실행되는 바이너리를 제공합니다. 이 둘은 호환되지 않습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) standalone 빌드 특성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js의 standalone 모드는 필요한 파일만 .next/standalone 디렉토리로 복사합니다. sharp도 포함되지만, 환경이 다르면 포함되어도 실행되지 않습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3) fallback이 작동하지 않음&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;production에서는 sharp가 명시적으로 포함되어 있기 때문에 fallback이 일어나지 않습니다. 따라서 sharp가 실행되지 못하면 곧바로 오류가 발생합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 운영 환경에서는 sharp를 써야 하는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js는 기본적으로 sharp를 우선 사용하고, 문제가 있을 때 squoosh로 대체합니다. 하지만 공식 문서에서도 &lt;b&gt;운영 환경에서는 sharp 사용을 강력하게 권장&lt;/b&gt;하고 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;sharp는 C++ 기반 네이티브 모듈로 고속 이미지 처리가 가능하고, 리소스 사용량도 효율적입니다.&lt;/li&gt;
&lt;li&gt;반면 squoosh는 범용성과 안정성은 높지만, 이미지 처리 성능은 상대적으로 낮습니다.&lt;/li&gt;
&lt;li&gt;특히 서버 트래픽이 많거나 이미지 크기가 큰 환경에서는 sharp가 훨씬 유리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 해결 방법: sharp를 Alpine에 맞게 재빌드&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Alpine 환경에서 sharp를 정상적으로 실행하려면 해당 환경에 맞는 바이너리를 직접 빌드해야 합니다. 다음 명령어를 통해 musl libc 기반으로 재컴파일합니다.&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;npm rebuild sharp --platform=linuxmusl --arch=x64
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령은 현재 컨테이너 환경에 맞는 .node 바이너리를 생성합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. Dockerfile 예시&lt;/h2&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;FROM node:18-alpine AS base

# Install dependencies only when needed
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app

COPY package.json package-lock.json* ./
RUN npm ci
RUN npm rebuild sharp --platform=linuxmusl --arch=x64
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sharp는 반드시 dependencies에 포함되어야 standalone 모드에서도 복사됩니다. devDependencies에만 있으면 누락될 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 요약&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개발 환경에서는 sharp가 설치되거나, 실패해도 squoosh가 자동으로 대체해주기 때문에 문제가 드러나지 않는다.&lt;/li&gt;
&lt;li&gt;운영 환경에서는 sharp가 실행되지 못하면 fallback 없이 오류가 발생한다.&lt;/li&gt;
&lt;li&gt;Alpine 리눅스는 musl libc 기반이므로, 기본 sharp 바이너리와 호환되지 않는다.&lt;/li&gt;
&lt;li&gt;해결 방법은 npm rebuild sharp --platform=linuxmusl 명령어로 환경에 맞는 바이너리를 재컴파일하는 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js의 standalone + Docker 배포는 효율적이지만, 네이티브 모듈이 포함될 경우 실행 환경에 맞는 빌드 전략이 필요합니다. 특히 이미지 최적화를 안정적으로 운영하려면 sharp를 환경에 맞게 구성해주는 과정이 필요합니다.&lt;/p&gt;</description>
      <category>React</category>
      <category>docker</category>
      <category>Next.js</category>
      <category>Standalone</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/102</guid>
      <comments>https://oagree0123.tistory.com/entry/Nextjs-standalone-%EB%B0%B0%ED%8F%AC-sharp-missing-in-production-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0#entry102comment</comments>
      <pubDate>Wed, 7 May 2025 21:08:10 +0900</pubDate>
    </item>
    <item>
      <title>HTTPS는 되는데 HTTP는 왜 안 될까?</title>
      <link>https://oagree0123.tistory.com/entry/HTTPS%EB%8A%94-%EB%90%98%EB%8A%94%EB%8D%B0-HTTP%EB%8A%94-%EC%99%9C-%EC%95%88-%EB%90%A0%EA%B9%8C</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;NCP 리스너 설정으로 해결한 사례&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;도메인 연결과 SSL 인증서 적용까지 모두 마쳤다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;브라우저에서 &lt;/span&gt;&lt;span&gt;https://example.com&lt;/span&gt;&lt;span&gt;으로 접속했을 때도 문제없이 작동했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그런데 &lt;/span&gt;&lt;span&gt;http://example.com&lt;/span&gt;&lt;span&gt;으로 접속해보니 아무 반응이 없었다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;서버 로그에도 기록이 없고, 요청이 들어온 흔적조차 없었다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;결국 원인은 &lt;/span&gt;&lt;span&gt;&lt;b&gt;로드밸런서의 리스너 설정 부족&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이었다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;HTTP와 HTTPS, 뭐가 다를까?&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;웹사이트 주소는 &lt;/span&gt;&lt;span&gt;http://&lt;/span&gt;&lt;span&gt; 또는 &lt;/span&gt;&lt;span&gt;https://&lt;/span&gt;&lt;span&gt;로 시작한다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;단순히 알파벳 하나의 차이처럼 보이지만, 실제로는 보안 수준이 크게 다르다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;true&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;HTTP&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 데이터를 암호화하지 않고 전송한다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;요청이 중간에 가로채이면, 내용이 그대로 노출될 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;HTTPS&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: SSL 인증서를 통해 데이터를 암호화해서 전송한다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;비밀번호, 쿠키, 개인정보 등을 안전하게 보호할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;요즘은 대부분의 서비스가 HTTPS를 기본으로 사용한다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;브라우저는 HTTPS가 없는 사이트에 보안 경고를 띄우고,&lt;/span&gt;&lt;br /&gt;&lt;span&gt;검색 엔진도 HTTPS 사용 여부를 평가에 반영한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;HTTPS는 잘 되는데 HTTP는 왜 안 될까?&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;HTTPS로 접속했을 때는 잘 작동했기 때문에,&lt;/span&gt;&lt;br /&gt;&lt;span&gt;서버나 포트 설정 문제는 아니라고 판단했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;하지만 HTTP로 접속했을 땐 응답 자체가 없었다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;서버에 요청이 도달하지 않았다는 건,&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;로드밸런서에서 요청을 처리하지 못한 것&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이라는 의미다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;로드밸런서에서 리스너는 어떤 역할을 할까?&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;NCP의 로드밸런서는 요청을 받아 처리할 포트를&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;리스너(listener)&lt;/b&gt;를 통해 정의한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;80&lt;/span&gt;&lt;span&gt; 포트 리스너: HTTP 요청 수신&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;443&lt;/span&gt;&lt;span&gt; 포트 리스너: HTTPS 요청 수신&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;LB는 리스너가 등록된 포트만 처리할 수 있기 때문에,&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;HTTP 요청을 처리하려면 80 포트 리스너가 반드시 필요&lt;/b&gt;&lt;/span&gt;&lt;span&gt;하다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-02 오후 2.45.17.png&quot; data-origin-width=&quot;1846&quot; data-origin-height=&quot;265&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QQHF9/btsNHOd9fWt/h7nKYN0A7Z5P6xlkAAdy61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QQHF9/btsNHOd9fWt/h7nKYN0A7Z5P6xlkAAdy61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QQHF9/btsNHOd9fWt/h7nKYN0A7Z5P6xlkAAdy61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQQHF9%2FbtsNHOd9fWt%2Fh7nKYN0A7Z5P6xlkAAdy61%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;1846&quot; height=&quot;265&quot; data-filename=&quot;스크린샷 2025-05-02 오후 2.45.17.png&quot; data-origin-width=&quot;1846&quot; data-origin-height=&quot;265&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;해결 방법: HTTP 리스너 추가 + HTTPS 리디렉션 설정&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;문제 해결을 위해 다음 두 가지를 설정했다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;80 포트 리스너 추가&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;HTTP 요청을 HTTPS로 리디렉션&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;설정 단계 (NCP 콘솔 기준)&lt;/span&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;1. 리스너 추가&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;포트: &lt;/span&gt;&lt;span&gt;80&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;프로토콜: &lt;/span&gt;&lt;span&gt;HTTP&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;동작: &lt;/span&gt;&lt;span&gt;리디렉션&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;2. 리디렉션 규칙 설정&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;리디렉션 대상: &lt;/span&gt;&lt;span&gt;https://${host}${path}&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;타겟 그룹은 연결하지 않음&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;rarr; 리디렉션만 수행하고 서버에 전달하지 않기 때문&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2025-05-02 오후 2.48.20.png&quot; data-origin-width=&quot;949&quot; data-origin-height=&quot;448&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdSfzV/btsNJGL9mJn/jndjZyM2qrJwDj5Wjw0iE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdSfzV/btsNJGL9mJn/jndjZyM2qrJwDj5Wjw0iE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdSfzV/btsNJGL9mJn/jndjZyM2qrJwDj5Wjw0iE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdSfzV%2FbtsNJGL9mJn%2FjndjZyM2qrJwDj5Wjw0iE1%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;949&quot; height=&quot;448&quot; data-filename=&quot;스크린샷 2025-05-02 오후 2.48.20.png&quot; data-origin-width=&quot;949&quot; data-origin-height=&quot;448&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;설정 후 확인&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이제 &lt;/span&gt;&lt;span&gt;http://example.com&lt;/span&gt;&lt;span&gt;으로 접속해보면&lt;/span&gt;&lt;br /&gt;&lt;span&gt;자동으로 &lt;/span&gt;&lt;span&gt;https://example.com&lt;/span&gt;&lt;span&gt;으로 리디렉션되고,&lt;/span&gt;&lt;br /&gt;&lt;span&gt;서버도 정상적으로 요청을 처리한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;정리&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;true&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;HTTP는 암호화되지 않은 연결이고,&lt;/span&gt;&lt;br /&gt;&lt;span&gt;HTTPS는 암호화된 안전한 연결이다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;NCP에서는 SSL 인증서를 &lt;/span&gt;&lt;span&gt;&lt;b&gt;서버가 아닌 로드밸런서에 등록&lt;/b&gt;&lt;/span&gt;&lt;span&gt;한다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;서버는 항상 &lt;/span&gt;&lt;span&gt;&lt;b&gt;80 포트&lt;/b&gt;&lt;/span&gt;&lt;span&gt;로 요청을 받는다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;HTTP 요청이 무시된다면, &lt;/span&gt;&lt;span&gt;&lt;b&gt;LB에 80 포트 리스너가 없을 가능성&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이 높다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;HTTP 요청을 HTTPS로 전환하려면,&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;로드밸런서에서 리디렉션 설정을 직접 해야 한다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;참고: 서버에서 리디렉션하면 안 되는 이유&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;ldquo;그냥 Nginx에서 리디렉션 설정하면 안 되나?&amp;rdquo;라는 생각이 들 수 있다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;하지만 NCP 구조에서는 SSL 인증서가 &lt;/span&gt;&lt;span&gt;&lt;b&gt;서버가 아니라 LB에만 등록&lt;/b&gt;&lt;/span&gt;&lt;span&gt;된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;HTTP 요청도 &lt;/span&gt;&lt;span&gt;&lt;b&gt;LB에서 걸러지면 서버까지 도달하지 못하기 때문에&lt;/b&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;br /&gt;&lt;span&gt;리디렉션은 &lt;/span&gt;&lt;span&gt;&lt;b&gt;서버가 아닌 로드밸런서 레벨&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에서 처리해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;마무리&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;HTTPS만 적용했다고 해서 끝이 아니다.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;HTTP 요청까지 안전하게 HTTPS로 전환되도록 유도하는 구성&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이 필요하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이번 설정을 통해, 단순히 보안을 적용하는 것을 넘어서&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;b&gt;사용자의 진입 경로를 관리하고, 서비스를 완성도 있게 운영하는 방식&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 배웠다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Web</category>
      <category>HTTP</category>
      <category>https</category>
      <category>Lb</category>
      <category>ncp</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/101</guid>
      <comments>https://oagree0123.tistory.com/entry/HTTPS%EB%8A%94-%EB%90%98%EB%8A%94%EB%8D%B0-HTTP%EB%8A%94-%EC%99%9C-%EC%95%88-%EB%90%A0%EA%B9%8C#entry101comment</comments>
      <pubDate>Fri, 2 May 2025 14:51:23 +0900</pubDate>
    </item>
    <item>
      <title>async/await은 왜 쓰는가? : JS 비동기 처리하기</title>
      <link>https://oagree0123.tistory.com/entry/asyncawait%EC%9D%80-%EC%99%9C-%EC%93%B0%EB%8A%94%EA%B0%80-JS-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;들어가는 말&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에 async/await에 대해 간단히 정리한 적이 있다. 하지만 그때는 문법 위주로만 설명하다 보니,&lt;br /&gt;비동기 흐름이 왜 그렇게 발전했는지, 무엇이 개선되고 어떤 점을 주의해야 하는지는 충분히 다루지 못했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글은 그 아쉬움을 채우기 위해 준비했다. 동기와 비동기의 개념부터 시작해,&lt;br /&gt;콜백 &amp;rarr; Promise &amp;rarr; async/await으로 이어지는 흐름을 차근차근 짚어보며&lt;br /&gt;비동기를 올바르게 다루는 사고 방식을 정리해보려 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;이 글을 통해 배우는 것&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동기(Sync) vs 비동기(Async)의 차이&lt;/li&gt;
&lt;li&gt;자바스크립트에서의 비동기 처리 흐름: 콜백 &amp;rarr; Promise &amp;rarr; async/await&lt;/li&gt;
&lt;li&gt;각각의 방식이 해결한 문제와 한계&lt;/li&gt;
&lt;li&gt;병렬 처리 시 성능 차이와 실제 사용 전략&lt;/li&gt;
&lt;/ul&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;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;console.log('A');
console.log('B');
console.log('C');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드는 예상대로 A &amp;rarr; B &amp;rarr; C 순서로 실행된다. 앞선 작업이 끝나야 다음 작업이 실행되는 구조이기 때문이다.&lt;br /&gt;이처럼 동기 방식은 단순하고 직관적이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 실제 환경에서는 모든 작업이 순차적으로만 진행되지는 않는다.&lt;br /&gt;예를 들어, 웹 페이지가 서버에 데이터를 요청하는 동안 사용자는 화면을 계속 사용할 수 있어야 한다.&lt;br /&gt;이때 필요한 것이 비동기 처리다.&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;p data-ke-size=&quot;size16&quot;&gt;예를 들어 식당에서 주문을 하면, 요리가 나오는 동안 주방에서는 다른 손님의 음식을 동시에 만들 수 있다.&lt;br /&gt;마찬가지로 자바스크립트에서는 서버 요청, 파일 읽기 등 시간이 오래 걸리는 작업을 비동기로 처리해&lt;br /&gt;전체 흐름이 멈추지 않도록 한다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;console.log('A');

setTimeout(() =&amp;gt; {
  console.log('B');
}, 1000);

console.log('C');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드는 A &amp;rarr; C &amp;rarr; B 순서로 출력된다. setTimeout은 비동기적으로 실행되기 때문에 다음 줄이 먼저 실행된다.&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;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;
getUser(id, function(user) {
  getPosts(user, function(posts) {
    updateUI(posts);
  });
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 작업이 복잡해질수록 콜백이 중첩되면서 코드가 오른쪽으로 밀리고, 가독성이 크게 떨어지게 된다.&lt;br /&gt;이런 구조를 흔히 &quot;콜백 지옥(callback hell)&quot;이라고 부른다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;콜백 방식의 문제점&lt;/h3&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;try-catch로 에러를 잡기 어렵다&lt;/li&gt;
&lt;li&gt;로직 분기나 재사용이 불편하다&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Promise의 등장&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하기 위해 ES6에서 Promise가 도입되었다. Promise는 미래에 완료될 작업을 표현하는 객체다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;getUser(id)
  .then(user =&amp;gt; getPosts(user))
  .then(posts =&amp;gt; updateUI(posts))
  .catch(err =&amp;gt; handleError(err));
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;개선된 점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;then 체인으로 흐름을 선형적으로 표현할 수 있다&lt;/li&gt;
&lt;li&gt;catch로 일괄적인 에러 처리가 가능하다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 복잡한 조건이나 반복문 안에서는 then 안에 또 then이 들어가는 중첩 문제가 여전히 발생할 수 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;async/await의 등장&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise 기반을 유지하면서, 코드 흐름을 더 직관적으로 만들 수 있도록 async/await 문법이 도입되었다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;async function renderPage() {
  try {
    const user = await getUser(id);
    const posts = await getPosts(user);
    updateUI(posts);
  } catch (err) {
    handleError(err);
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;async/await의 장점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 설명&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;가독성&lt;/td&gt;
&lt;td&gt;동기 코드처럼 읽힌다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;예외 처리&lt;/td&gt;
&lt;td&gt;try-catch로 자연스럽다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;흐름 제어&lt;/td&gt;
&lt;td&gt;조건문, 반복문과 잘 어울린다&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;async/await 사용 시 주의점 &amp;ndash; 직렬 vs 병렬&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;await를 연속으로 사용할 경우 작업이 순차적으로 실행된다. 이 경우 불필요하게 시간이 오래 걸릴 수 있다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;직렬 실행 예시&lt;/h3&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;const user = await fetchUser();
const posts = await fetchPosts();
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;병렬 실행 예시&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const [user, posts] = await Promise.all([
  fetchUser(),
  fetchPosts()
]);
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise.all을 사용하면 동시에 작업을 시작하고, 모든 작업이 끝날 때까지 기다린다. 이 방식은 처리 속도 면에서 훨씬 효율적이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실험: 직렬 vs 병렬 처리 시간 비교&lt;/h2&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;function delay(ms) {
  return new Promise(resolve =&amp;gt; setTimeout(resolve, ms));
}

async function serialExecution() {
  await delay(1000);
  await delay(1000);
  console.log('직렬 실행 완료'); // 약 2초 소요
}

async function parallelExecution() {
  await Promise.all([delay(1000), delay(1000)]);
  console.log('병렬 실행 완료'); // 약 1초 소요
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;정리 요약&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항목 콜백 Promise async/await&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;구조&lt;/td&gt;
&lt;td&gt;중첩 함수&lt;/td&gt;
&lt;td&gt;체이닝&lt;/td&gt;
&lt;td&gt;동기 스타일&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;가독성&lt;/td&gt;
&lt;td&gt;낮음&lt;/td&gt;
&lt;td&gt;보통&lt;/td&gt;
&lt;td&gt;높음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;에러 처리&lt;/td&gt;
&lt;td&gt;어렵다&lt;/td&gt;
&lt;td&gt;.catch()&lt;/td&gt;
&lt;td&gt;try-catch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;흐름 제어&lt;/td&gt;
&lt;td&gt;제한적&lt;/td&gt;
&lt;td&gt;보통&lt;/td&gt;
&lt;td&gt;유연함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;병렬 처리&lt;/td&gt;
&lt;td&gt;어려움&lt;/td&gt;
&lt;td&gt;가능&lt;/td&gt;
&lt;td&gt;가능 (Promise.all 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;async/await는 단순히 편한 문법이 아니라,&lt;br /&gt;비동기 흐름을 명확하게 설계할 수 있도록 도와주는 중요한 도구다.&lt;br /&gt;제대로 활용하려면 흐름 제어와 병렬 처리 개념까지 함께 이해하는 것이 필요하다.&lt;/p&gt;</description>
      <category>JavaScript</category>
      <category>async/await</category>
      <category>Callback</category>
      <category>JS</category>
      <category>Promise</category>
      <category>비동기</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/100</guid>
      <comments>https://oagree0123.tistory.com/entry/asyncawait%EC%9D%80-%EC%99%9C-%EC%93%B0%EB%8A%94%EA%B0%80-JS-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0#entry100comment</comments>
      <pubDate>Fri, 2 May 2025 13:57:03 +0900</pubDate>
    </item>
    <item>
      <title>Portal과 Compound 패턴으로 Modal 만들기</title>
      <link>https://oagree0123.tistory.com/entry/Portal%EA%B3%BC-Compound-%ED%8C%A8%ED%84%B4%EC%9C%BC%EB%A1%9C-Modal-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;지난 글에서는 Select 컴포넌트를 Compound Component 패턴으로 관리하는 방법을 소개했다. 이번에는 이 패턴을 Modal 컴포넌트에도 적용해보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Modal은 프로젝트 어디에서나 자주 사용된다. 그래서 더더욱 잘 구조화해서 만들어두는 게 중요하다. 이번 글에서는 &lt;b&gt;Portal을 이용하고, Compound Component 패턴을 적용해 Modal을 공통 컴포넌트로 깔끔하게 만드는 방법&lt;/b&gt;을 정리해본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Modal을 만들 때 고려한 기본 원칙은 세 가지였다:&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;Portal을 이용해 Modal을 body 바깥에 띄운다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;useModalStore 같은 전역 상태 훅을 사용해 열고 닫을 수 있게 한다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Compound Component 패턴으로 구조를 나눠 자유롭게 조합할 수 있게 한다.&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 Portal을 사용했을까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Modal은 항상 시각적으로 화면 최상단에 떠야 하고, 다른 레이아웃 요소들의 영향을 받아서는 안 된다. Portal을 사용하면 다음과 같은 장점이 있다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;레이아웃 간섭이 없다:&lt;/b&gt; 모달이 컴포넌트 트리 어디에 있든 body에 직접 붙어 렌더링된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스타일 충돌 최소화:&lt;/b&gt; 부모 요소의 CSS(position, overflow 등) 영향을 받지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;구조적 분리:&lt;/b&gt; 렌더링 구조를 논리 구조와 분리해 유지보수가 쉬워진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Portal 없이 모달을 구현하면 부모의 overflow: hidden 같은 스타일에 의해 모달이 잘리거나 스크롤이 막히는 문제가 생길 수 있다. 그래서 Portal은 Modal에서 사실상 필수다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 상태 관리를 전역으로 했을까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Modal은 다양한 위치, 다양한 이벤트에서 열릴 수 있어야 한다. 매번 컴포넌트마다 상태를 따로 관리하면 관리 포인트가 늘어나고 일관성도 떨어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 Modal의 열림/닫힘 상태를 전역 상태로 관리했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;상태 관리 구조 예시:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;// useModalStore.ts
import { create } from 'zustand';

type ModalState = {
  isOpen: boolean;
  modalProps: Partial&amp;lt;ModalProps&amp;gt;;
};

const initialState: ModalState = {
  isOpen: false,
  modalProps: {},
};

export const useModalStore = create&amp;lt;ModalState&amp;gt;(() =&amp;gt; ({
  ...initialState,
}));

export const modalActions = {
  openModal: (props: Partial&amp;lt;ModalProps&amp;gt;) =&amp;gt;
    useModalStore.setState({ isOpen: true, modalProps: props }),
  closeModal: () =&amp;gt;
    useModalStore.setState({ isOpen: false, modalProps: {} }),
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;사용 예시:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;modalActions.openModal({
  title: '삭제 확인',
  description: '삭제하면 복구할 수 없습니다.',
  onConfirm: handleDelete,
});
&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;어디서든 modalActions.openModal()을 호출하면 모달을 열 수 있고, 상태는 전역으로 일관되게 관리된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Modal 기본 구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Portal과 전역 상태를 이용해 기본적인 Modal 구조를 만들었다. 핵심은 다음과 같다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Portal을 통해 #portal DOM에 렌더링&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Compound Component로 구조 나누기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Modal은 상황에 따라 다양한 모습으로 사용된다.&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 위해 Modal을 다음과 같이 쪼갰다:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트 역할&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Modal.Root&lt;/td&gt;
&lt;td&gt;Portal을 통한 전체 구조&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modal.Header&lt;/td&gt;
&lt;td&gt;제목을 표시하는 영역&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modal.Body&lt;/td&gt;
&lt;td&gt;본문을 표시하는 영역&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Modal.Footer&lt;/td&gt;
&lt;td&gt;버튼 영역 (Confirm/Cancel)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한 조합만 골라서 사용할 수 있다. 예를 들면:&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;Modal&amp;gt;
  &amp;lt;Modal.Header title=&quot;정말 삭제하시겠습니까?&quot; /&amp;gt;
  &amp;lt;Modal.Body&amp;gt;
    삭제하면 복구할 수 없습니다.
  &amp;lt;/Modal.Body&amp;gt;
  &amp;lt;Modal.Footer
    onConfirm={handleDelete}
    onCancel={modalActions.closeModal}
    confirmText=&quot;삭제&quot;
    cancelText=&quot;취소&quot;
  /&amp;gt;
&amp;lt;/Modal&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;복잡한 Modal도 쉽게 만들 수 있다&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Compound 패턴을 적용하면 입력폼이 들어간 복잡한 Modal도 쉽게 만들 수 있다.&lt;/p&gt;
&lt;pre class=&quot;xml&quot;&gt;&lt;code&gt;&amp;lt;Modal&amp;gt;
  &amp;lt;Modal.Header title=&quot;회원가입&quot; /&amp;gt;
  &amp;lt;Modal.Body&amp;gt;
    &amp;lt;input type=&quot;text&quot; placeholder=&quot;이름 입력&quot; /&amp;gt;
    &amp;lt;input type=&quot;email&quot; placeholder=&quot;이메일 입력&quot; /&amp;gt;
  &amp;lt;/Modal.Body&amp;gt;
  &amp;lt;Modal.Footer
    onConfirm={handleSubmit}
    confirmText=&quot;가입하기&quot;
    type=&quot;alert&quot;
  /&amp;gt;
&amp;lt;/Modal&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Body 영역 안에는 자유롭게 폼, 이미지, 설명 등을 넣을 수 있고, Modal 컴포넌트 자체를 수정할 필요가 없다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;왜 Compound Component 패턴을 썼을까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Modal을 하나의 컴포넌트로 만들면 다양한 옵션을 props로 관리해야 해서 컴포넌트가 비대해지고, 조건 분기 로직이 복잡해진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 Compound 패턴은:&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 Modal처럼 다양한 변형이 필요한 UI에서는 Compound 패턴의 이점이 매우 크다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Modal 컴포넌트를 Portal과 Compound Component 패턴을 활용해 구조화하면서 느낀 점은 이렇다.&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;다양한 형태와 사용 방법을 지원해야 하는 컴포넌트라면, Compound Component 패턴은 충분히 고려할 가치가 있다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 상황에 무조건 적용해야 하는 것은 아니지만, Modal처럼 &lt;b&gt;확장 가능성과 변형 가능성&lt;/b&gt;이 중요한 컴포넌트에는&lt;br /&gt;초기에 이런 구조를 잡아두는 것이 장기적으로 큰 도움이 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 프로젝트를 돌아보면서, 특정 UI를 더 유연하고 확장성 있게 관리하고 싶다면 &lt;br /&gt;Compound Component 패턴을 한 번 고려해보는 것도 좋은 방법일 것이다.&lt;/p&gt;</description>
      <category>React</category>
      <category>compound component</category>
      <category>react</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/99</guid>
      <comments>https://oagree0123.tistory.com/entry/Portal%EA%B3%BC-Compound-%ED%8C%A8%ED%84%B4%EC%9C%BC%EB%A1%9C-Modal-%EB%A7%8C%EB%93%A4%EA%B8%B0#entry99comment</comments>
      <pubDate>Tue, 29 Apr 2025 14:31:51 +0900</pubDate>
    </item>
    <item>
      <title>공통 컴포넌트를 유연하게 설계하는 방법: Compound Component 패턴 적용하기</title>
      <link>https://oagree0123.tistory.com/entry/%EA%B3%B5%ED%86%B5-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EB%A5%BC-%EC%9C%A0%EC%97%B0%ED%95%98%EA%B2%8C-%EC%84%A4%EA%B3%84%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-Compound-Component-%ED%8C%A8%ED%84%B4-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;React에서 여러 기능을 가진 UI를 만들 때, 각각의 역할을 분리하여 조립 가능한 형태로 구성하는 것이 중요합니다. 이때 유용하게 쓸 수 있는 방법이 바로 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Compound Component 패턴&lt;/b&gt;&lt;/span&gt;&lt;span&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이번 글에서는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;공통 컴포넌트를 더 유연하고 확장 가능하게 만들기 위해 Compound Component 패턴을 선택한 이유와 장점&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 소개하고, 이를 &lt;/span&gt;&lt;span&gt;Select&lt;/span&gt;&lt;span&gt; 컴포넌트 예시로 구체적으로 풀어보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;1. 왜 Compound Component 패턴을 선택했을까?&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;기능과 UI를 하나의 컴포넌트에 모두 포함시키면 코드가 비대해지고, 작은 수정이나 새로운 기능 추가에도 전체 구조를 건드려야 해서 유지보수와 확장이 어렵습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;반면, Compound Component 패턴을 사용하면 다음과 같은 장점이 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;유연성&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 필요한 컴포넌트만 골라 자유롭게 조합할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;책임 분리&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 로직은 Provider에, UI는 각각의 컴포넌트에 나누어 관리할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;재사용성&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 버튼, 옵션 등 다양한 파트를 원하는 대로 커스터마이징할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;변경 대응력&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: UI 구조나 디자인이 변경되더라도, 핵심 로직은 유지되기 때문에 수정이 간편합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히, 추가 요구사항이나 디자인 변경이 생겨도 일부 컴포넌트만 수정하면 되기 때문에 빠르게 대응할 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;2. 예시로 살펴보기: Select 컴포넌트 만들기&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Compound Component 패턴을 적용해 &lt;/span&gt;&lt;span&gt;Select&lt;/span&gt;&lt;span&gt; 컴포넌트를 만들어보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;기본 구조&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;&amp;lt;Select&amp;gt;
  &amp;lt;Select.Trigger&amp;gt;Choose an option&amp;lt;/Select.Trigger&amp;gt;
  &amp;lt;Select.Options&amp;gt;
    &amp;lt;Select.Option value=&quot;apple&quot;&amp;gt;Apple&amp;lt;/Select.Option&amp;gt;
    &amp;lt;Select.Option value=&quot;banana&quot;&amp;gt;Banana&amp;lt;/Select.Option&amp;gt;
  &amp;lt;/Select.Options&amp;gt;
&amp;lt;/Select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이런 구조 덕분에 사용자는 &lt;/span&gt;&lt;span&gt;&amp;lt;Select&amp;gt;&lt;/span&gt;&lt;span&gt; 내부에 &lt;/span&gt;&lt;span&gt;Trigger&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Option&lt;/span&gt;&lt;span&gt;을 자유롭게 배치할 수 있어, 다양한 레이아웃과 스타일을 쉽게 적용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;✨ 여기서 Compound Component 패턴의 진짜 장점은?&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;기본적인 Select UI를 구현하는 것에 그치지 않고,&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;나중에 &lt;/span&gt;&lt;span&gt;&lt;b&gt;옵션 항목마다 아이콘이나 추가 설명 텍스트를 붙인다든지&lt;/b&gt;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;옵션을 그룹화하여 &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;Select.Group&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; 형태로 확장&lt;/b&gt;&lt;/span&gt;&lt;span&gt;한다든지,&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;트리거 버튼을 다른 스타일이나 동작으로 바꾼다든지&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 하는 다양한 요구사항이 생겨도&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;핵심 로직은 그대로 유지한 채, 필요한 컴포넌트만 수정하거나 추가하면 대응할 수 있다는 점&lt;/b&gt;&lt;/span&gt;&lt;span&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;즉, UI나 인터랙션에 새로운 변화가 들어와도, &lt;/span&gt;&lt;span&gt;&lt;b&gt;전체를 다시 짜지 않고 각 역할별 컴포넌트만 교체하거나 조합하는 방식으로 빠르게 대응할 수 있습니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 Compound Component 패턴은 &quot;변경에 유연하고, 유지보수가 쉬운 구조&quot;를 자연스럽게 만들어줍니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;예를 들어, 옵션에 아이콘을 추가하는 확장도 쉽게 가능합니다.&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;&amp;lt;Select&amp;gt;
  &amp;lt;Select.Trigger&amp;gt;Select a fruit&amp;lt;/Select.Trigger&amp;gt;
  &amp;lt;Select.Options&amp;gt;
    &amp;lt;Select.Option value=&quot;apple&quot;&amp;gt;
        Apple
    &amp;lt;/Select.Option&amp;gt;
    &amp;lt;Select.Option value=&quot;banana&quot;&amp;gt;
        Banana
    &amp;lt;/Select.Option&amp;gt;
  &amp;lt;/Select.Options&amp;gt;
&amp;lt;/Select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;또는 옵션을 그룹화하고 싶을 때도 별도의 &lt;/span&gt;&lt;span&gt;Select.Group&lt;/span&gt;&lt;span&gt; 컴포넌트를 추가하는 식으로 유연하게 확장할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;&amp;lt;Select&amp;gt;
  &amp;lt;Select.Trigger&amp;gt;Choose an item&amp;lt;/Select.Trigger&amp;gt;
  &amp;lt;Select.Options&amp;gt;
    &amp;lt;Select.Group label=&quot;Fruits&quot;&amp;gt;
      &amp;lt;Select.Option value=&quot;apple&quot;&amp;gt;Apple&amp;lt;/Select.Option&amp;gt;
      &amp;lt;Select.Option value=&quot;banana&quot;&amp;gt;Banana&amp;lt;/Select.Option&amp;gt;
    &amp;lt;/Select.Group&amp;gt;
    &amp;lt;Select.Group label=&quot;Vegetables&quot;&amp;gt;
      &amp;lt;Select.Option value=&quot;carrot&quot;&amp;gt;Carrot&amp;lt;/Select.Option&amp;gt;
      &amp;lt;Select.Option value=&quot;broccoli&quot;&amp;gt;Broccoli&amp;lt;/Select.Option&amp;gt;
    &amp;lt;/Select.Group&amp;gt;
  &amp;lt;/Select.Options&amp;gt;
&amp;lt;/Select&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이처럼 구조를 미리 잘 나눠두면, 다양한 변경이나 확장 요구가 들어와도 부담 없이 대응할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이런 구조 덕분에 사용자는 &lt;/span&gt;&lt;span&gt;&amp;lt;Select&amp;gt;&lt;/span&gt;&lt;span&gt; 내부에 &lt;/span&gt;&lt;span&gt;Trigger&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Options&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;Option&lt;/span&gt;&lt;span&gt;을 자유롭게 배치할 수 있어, 다양한 레이아웃과 스타일을 쉽게 적용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;3. SelectContext로 상태 공유하기&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Select 컴포넌트는 열림 여부(&lt;/span&gt;&lt;span&gt;isOpen&lt;/span&gt;&lt;span&gt;), 현재 선택된 값(&lt;/span&gt;&lt;span&gt;value&lt;/span&gt;&lt;span&gt;), 토글 함수(&lt;/span&gt;&lt;span&gt;toggle&lt;/span&gt;&lt;span&gt;), 선택 함수(&lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt;) 같은 상태와 동작을 공유합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Context를 이용하면 prop drilling 없이 필요한 컴포넌트끼리 상태를 자연스럽게 공유할 수 있어 확장성과 유지보수성이 높아집니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const SelectContext = createContext&amp;lt;SelectContextProps | undefined&amp;gt;(undefined);

export const useSelectContext = () =&amp;gt; {
  const context = useContext(SelectContext);
  if (!context) {
    throw new Error('useSelectContext must be used within a SelectProvider');
  }
  return context;
};&lt;/code&gt;&lt;/pre&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;4. SelectProvider로 상태 관리하기&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Provider 컴포넌트에서는 열림/닫힘, 선택 기능 같은 상태를 집중 관리합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  const handleClickOutside = (event: MouseEvent) =&amp;gt; {
    if (localRef.current &amp;amp;&amp;amp; !localRef.current.contains(event.target as Node)) {
      close();
    }
  };

  document.addEventListener('mousedown', handleClickOutside);
  return () =&amp;gt; {
    document.removeEventListener('mousedown', handleClickOutside);
  };
}, [close]);&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태를 하나의 Provider에서 관리하면, 다양한 하위 컴포넌트들이 쉽게 동기화되고, 추가 로직이 생겨도 확장하기 쉽습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;5. 세부 컴포넌트 설계하기&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;(1) SelectTrigger&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const SelectTrigger = ({ children, disabled, ...props }: TriggerProps) =&amp;gt; {
  const { toggle } = useSelectContext();
  return (
    &amp;lt;button onClick={toggle} disabled={disabled} {...props}&amp;gt;
      {children}
    &amp;lt;/button&amp;gt;
  );
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;버튼 UI를 독립적으로 관리할 수 있어, 나중에 스타일이나 기능을 쉽게 교체할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;(2) SelectOptions&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;const SelectOptions = ({ children, ...props }: OptionsProps) =&amp;gt; {
  const { isOpen } = useSelectContext();
  if (!isOpen) {
    return null;
  }
  return &amp;lt;div {...props}&amp;gt;{children}&amp;lt;/div&amp;gt;;
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;드롭다운 리스트를 별도로 분리해 필요에 따라 애니메이션이나 다양한 효과를 추가할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;(3) SelectOption&lt;/span&gt;&lt;/h3&gt;
&lt;pre class=&quot;dust&quot;&gt;&lt;code&gt;const SelectOption = ({ value, children, ...props }: OptionProps) =&amp;gt; {
  const { select } = useSelectContext();
  return (
    &amp;lt;button onClick={() =&amp;gt; select(value)} {...props}&amp;gt;
      {children}
    &amp;lt;/button&amp;gt;
  );
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;옵션 하나하나를 독립적으로 다룰 수 있어, 아이콘 추가, 비활성화 옵션 같은 확장이 쉬워집니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;6. 마무리: Compound Component 패턴의 진짜 가치&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;공통 컴포넌트를 설계할 때 가장 중요한 것은 &lt;/span&gt;&lt;span&gt;&lt;b&gt;변화에 유연하게 대응할 수 있는 구조를 만드는 것&lt;/b&gt;&lt;/span&gt;&lt;span&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Compound Component 패턴은 이를 완벽하게 지원합니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;상태와 로직을 하나의 Provider에서 집중 관리하고&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;각각의 UI 파트를 독립적인 컴포넌트로 분리하며&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Context를 통해 컴포넌트 간 자연스럽고 안전한 연결을 유지합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이렇게 설계하면,&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;UI 수정이나 추가 기능 반영이 쉽고&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;새로운 요구사항에도 안정적으로 대응할 수 있으며&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;복잡한 공통 컴포넌트도 깔끔하게 관리할 수 있습니다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이번 글에서는 &lt;/span&gt;&lt;span&gt;Select&lt;/span&gt;&lt;span&gt; 컴포넌트를 예시로 살펴봤지만, Dropdown, Modal, Tabs, Accordion 등 다양한 컴포넌트에도 똑같은 원리를 적용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국, 변화에 강하고, 확장성과 유지보수가 뛰어난 공통 컴포넌트를 만들기 위해서는 Compound Component 패턴이 가장 강력한 선택지 중 하나입니다.&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>React</category>
      <category>compound component</category>
      <category>react</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/98</guid>
      <comments>https://oagree0123.tistory.com/entry/%EA%B3%B5%ED%86%B5-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8%EB%A5%BC-%EC%9C%A0%EC%97%B0%ED%95%98%EA%B2%8C-%EC%84%A4%EA%B3%84%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-Compound-Component-%ED%8C%A8%ED%84%B4-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0#entry98comment</comments>
      <pubDate>Tue, 29 Apr 2025 11:17:58 +0900</pubDate>
    </item>
    <item>
      <title>websocket과 라이브러리</title>
      <link>https://oagree0123.tistory.com/entry/websocket%EA%B3%BC-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;websocket&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;webSocket은 &lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;TCP &lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;&lt;span&gt;연결에서&lt;/span&gt;&lt;/span&gt;&amp;nbsp;클라이언트와 서버 사이에 &lt;br /&gt;지속적인 완전 양방향 연결 스트림을 만들어 주는 기술입니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;websocket의-특징&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;webSocket의 특징&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;양방향 통신 (Full-Duplex) 방식&lt;br /&gt;&amp;nbsp;
&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;일반적인 Http통신은 client가 요청을 보내는 경우에만 server가 응답하는 단방향 통신&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;실시간 네트워킹(Real Time-Networking)&lt;br /&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;웹 환경에서 연속된 데이터를 빠르게 노출 ex) 채팅, 주식&lt;/li&gt;
&lt;li&gt;여러 단발기에서 빠르게 데이터를 교환&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;최초 접속에서만 http프로토콜 위에서 handshaking을 하기 때문에 http header를 사용한다.&lt;/li&gt;
&lt;/ol&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;b&gt;Socket.io&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Socket.io는 node.js를 지원하고, websocket을 기반으로&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;실시간&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;&amp;nbsp;&lt;/span&gt;웹 애플리케이션을&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;위한&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;&amp;nbsp;&lt;/span&gt;JavaScript&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;라이브러리입니다&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #222222;&quot;&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비동기 이벤트 방식을 사용해&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실시간&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;으로 간단하게 데이터를 주고받을 수 있게 만들어 줍니다.&lt;/span&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;소켓 연결 실패 시 fallback을 통해 다른 방식으로 알아서 해당 클라이언트와 연결을 시도합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방 개념을 이용해 일부 클라이언트에게만 데이터를 전송하는 브로드캐스팅이 가능합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;SockJS&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Springframework에서 WebSocket을 기반으로 websocket과 비슷한 기능을 제공하는 javascript 라이브러리 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt; 스프링 메뉴얼에 webSocket 부분을 보면 브라우저 문제를 해결하기 위한 방법으로 SockJS를 솔루션으로 제시합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;크롬 뿐만 아니라 사파리, 파이어 폭스 등 websocket을 지원하지 않는 브라우저도 잘 작동이 된다.&lt;/span&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;&lt;b&gt;STOMP&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;STOMP는&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;WebSocket&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;위에서 동작하는 메세지 프로토콜로, &lt;br /&gt;클라이언트와 서버가 전송할 메시지 유형, 형식, 내용들을 정의하는 매커니즘입니다.&lt;/span&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;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;STOMP은&lt;span&gt;&amp;nbsp;&lt;/span&gt;Publish-Subscribe&lt;span&gt;&amp;nbsp;&lt;/span&gt;매커니즘을 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Broker를 통해서 다른 사용자들에게 메시지를 보내거나 &lt;br /&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 style=&quot;list-style-type: none;&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>JavaScript</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/86</guid>
      <comments>https://oagree0123.tistory.com/entry/websocket%EA%B3%BC-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC#entry86comment</comments>
      <pubDate>Thu, 28 Apr 2022 09:26:14 +0900</pubDate>
    </item>
    <item>
      <title>불변성은 왜 지켜야할까?</title>
      <link>https://oagree0123.tistory.com/entry/%EB%B6%88%EB%B3%80%EC%84%B1%EC%9D%80-%EC%99%9C-%EC%A7%80%EC%BC%9C%EC%95%BC%ED%95%A0%EA%B9%8C</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;불변성 (Immutability)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;불변성은 값이나 상태를 변경할 수 없는 것을 의미합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;프로그래밍에서 불변성은 데이터 원본의 훼손을 막는 것을 의미합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;간단히 말하자면, &lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;어떤 값을 직접적으로 변경하지 않고 새로운 값을 만들어내는 것입니다.&lt;/span&gt;&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;자바스크립트에서는 원시타입은 불변성을 지니지만, 객체타입은 값이 변할 수 있습니다.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;원시 타입&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;원시 타입에는 Boolean, Number, String, null, undefined, Symbol이 있습니다.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;먼저 코드를 보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1650990721331&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let str = &quot;example1&quot;;
str = &quot;example2&quot;;

console.log(str) // example2&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;위에서는 원시타입은 값을 변경할 수 없다고 했는데 위와 같은 결과가 나왔습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;사실, 위 과정은 값이 변경된 것이 아니라 새로 선언된 값이 메모리에 저장되고 &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333;&quot;&gt;변수가 새로운 메모리를 가리키는 것입니다.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;코드를 하나 더 보자면&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1650991070484&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let name = 'KIM';
let new_name = name;
name = 'LEE';

console.log(new_name); // KIM
console.log(name); // LEE&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;위와 같이 결과가 나온 이유는, 2번 줄에서 new_name이 name이 가리키고 있는&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;메모리를 같이 가리키고 있기 때문입니다.&lt;/span&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;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;객체 타입&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1650991230346&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var person = {
    name: 'KIM',
    age: 29,
}
var new_person = person;
person.name = 'LEE';

console.log(person.name); // 'LEE' 
console.log(new_person.name); // 'LEE'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;위 코드를 보면 객체 타입은 원시 타입과 다르게 이름이 모두 변경된 것을 볼 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;객체는 객체 내부의 값을 변경하면 객체를 참조하고 있는 다른 값들도 다 같이 변경됩니다.&lt;/span&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;b&gt;불변성은 왜 지켜야할까?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트는 상태값을 업데이트 할 때 얕은 비교를 수행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트는 &lt;span&gt;객체의 속성 하나하나를 비교하는게 아니라 참조값만 비교하여 상태 변화를 감지합니다.&lt;/span&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;span style=&quot;background-color: #ffffff; color: #9d9d9d;&quot;&gt;얕은 비교란 간단히 말하자면 객체, 배열, 함수와 같은 참조 타입들을 실제 내부 값까지 비교하지 않고 동일 참조인지(동일한 메모리 값을 사용하는지)를 비교하는 것을 뜻합니다.&lt;/span&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;우리가 컴포넌트를 리렌더링 해야하는 상황이 있다고 가정하고, 타입이 배열인 state를 바꿉니다.&lt;/li&gt;
&lt;li&gt;이때,&lt;span&gt;&amp;nbsp;&lt;/span&gt;state.push(1)을 통해 state 배열에 직접 접근하여 요소를 추가합니다.&lt;/li&gt;
&lt;li&gt;우리는 push 전과 다른 값이라고 생각하지만, 리엑트는 state라는 값은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;새로운 참조값이 아니기 때문에&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이전과 같은 값이라고 인식하고 리렌더링 하지 않습니다.&lt;/li&gt;
&lt;/ul&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;b&gt;불변성의 장점&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;1. 효율적인 상태업데이트 (얕은 비교 수행)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;얕은 비교란 객체의 프로퍼티를 하나하나 다 비교하지 않고, 객체의 참조 주소값만 변경되었는지 확인합니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;얕은 비교는 계산 리소스를 줄여주기 때문에 리액트는 효율적으로 상태를 업데이트 할 수 있습니다.&lt;/span&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;span&gt;2. 사이드 이펙트 방지 및 프로그래밍 구조의 단순성.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;원시타입은 애시당초 불변성 특징을 가지고 있지만 참조타입인 객체나 배열의 경우 새로운 값을 변경할 때 원본 데이터가 변경이 됩니다(불변성이 지켜지지 않습니다). 이렇게 원본 데이터가 변경될 경우, 이 원본데이터를 참조하고 있는 다른 객체에서 예상치 못한 오류가 발생할 수 있습니다. 프로그래밍의 복잡도도 올라갑니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;불변성을 지키면 이를 방지할 수 있습니다.&lt;/span&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;&lt;b&gt;&lt;span&gt;불변성을 지키는 방법&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;1. Spread 문법&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1650992458514&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 원시 타입
const [number, setNumber] = useState(0)
setState(10)

// 참조 타입
const [person, setPerson] = useState({ name: '', age: 29 })
setState({...person, name: 'KIM'})

setUsers(
  users.map(user =&amp;gt;
    user.id === id ? { ...user, name: &quot;KIM&quot; } : user
  )
);&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span&gt;2. immer 사용&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1650992649772&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import produce from &quot;immer&quot;;

const user = [
  {
    name: &quot;KIM&quot;,
    age: 29
  },
  {
    name: &quot;LEE&quot;,
    age: 32
  }
];

const new_user = produce(user, draft =&amp;gt; {
  draft.push({ name: &quot;PARK&quot; });
  draft[1].age = 28;
});&lt;/code&gt;&lt;/pre&gt;</description>
      <category>JavaScript</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/85</guid>
      <comments>https://oagree0123.tistory.com/entry/%EB%B6%88%EB%B3%80%EC%84%B1%EC%9D%80-%EC%99%9C-%EC%A7%80%EC%BC%9C%EC%95%BC%ED%95%A0%EA%B9%8C#entry85comment</comments>
      <pubDate>Wed, 27 Apr 2022 02:06:50 +0900</pubDate>
    </item>
    <item>
      <title>함수 스코프와 블록 스코프</title>
      <link>https://oagree0123.tistory.com/entry/%ED%95%A8%EC%88%98-%EC%8A%A4%EC%BD%94%ED%94%84%EC%99%80-%EB%B8%94%EB%A1%9D-%EC%8A%A4%EC%BD%94%ED%94%84</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;스코프&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;변수나 함수가 선언되어 사용할 수 있는 유효 범위&lt;span style=&quot;background-color: #ffffff;&quot;&gt;를 말합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;스코프는 크게 전역 스코프와 지역 스코프로 나누는데,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;지역 스코프에 오늘 정리할 &lt;b&gt;함수 스코프&lt;/b&gt;와 &lt;b&gt;블록 스코프&lt;/b&gt;가 있습니다.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;전역 스코프 : 어디든지 변수에 접근이 가능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;지역 스코프 : 정해진 범위 안에서 접근이 가능&lt;/span&gt;&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;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;함수 스코프&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;자바스크립트는 함수 스코프를 기본으로 사용합니다.&amp;nbsp; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;함수 스코프는 새로운 함수가 생성될 때마다 새로운 스코프가 발생되는데,&lt;/span&gt;&lt;/p&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;pre id=&quot;code_1650805229309&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function sayHello() {
  var hello = 'hello';
}
hello; //ReferenceError&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 보면, sayHello라는 함수가 생성된 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hello라는 변수가 sayHello라는 변수 안에서 선언되어 있으므로,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 스코프를 따라 ReferenceError가 나는 것을 볼 수 있습니다.&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;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;블록 스코프&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;블록 스코프는 블록 {}이 생성될 때마다 새로운 스코프가 형성되는 것을 의미합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;원래 자바스크립트는 함수 스코프를 따르지만, &lt;br /&gt;let과 const 키워드의 등장으로 블록 스코프를 사용하는 것도 가능해졌습니다.&lt;/span&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;pre id=&quot;code_1650805447898&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (true) {
  var abc = '123'; // var로 선언하면 블록에 의한 범위 제한이 없음
}
console.log(abc)  // 123&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1650805509099&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (true) {
  const abc = '123';  // const, let은 블록 스코프를 따름
}
console.log(abc) // ReferenceError&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;var로 선언한 abc는 출력이 잘 되는 것을 볼 수 있지만, const로 선언한 abc는 오류가 나는 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 말했듯이, const는 블록 스코프를 따르기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if문의 블록 스코프에서 벗어나 에러가 나는 것을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JavaScript</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/84</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%95%A8%EC%88%98-%EC%8A%A4%EC%BD%94%ED%94%84%EC%99%80-%EB%B8%94%EB%A1%9D-%EC%8A%A4%EC%BD%94%ED%94%84#entry84comment</comments>
      <pubDate>Sun, 24 Apr 2022 22:08:10 +0900</pubDate>
    </item>
    <item>
      <title>TCP 와 UDP 는 무엇이 다를까?</title>
      <link>https://oagree0123.tistory.com/entry/TCP-%EC%99%80-UDP-%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%B4-%EB%8B%A4%EB%A5%BC%EA%B9%8C</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;TCP와 UDP&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;TCP와 UDP는 전송계층&lt;span style=&quot;background-color: #ffffff;&quot;&gt;에서 데이터를 보내기 위해 사용되는 프로토콜입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;전송계층은 송신자와 수신자를 연결하는 통신서비스를 제공하는 계층으로, 쉽게 말해 데이터의 전달을 담당합니다.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;TCP는 Transmission Control Protocol의 약자이고, UDP는 User Datagram Protocol의 약자입니다.&lt;br /&gt;두 프로토콜은 모두&amp;nbsp;&lt;/span&gt;&lt;b&gt;패킷&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;을 한 컴퓨터에서 다른 컴퓨터로 전달해주는&amp;nbsp;&lt;/span&gt;IP 프로토콜&lt;span style=&quot;background-color: #ffffff;&quot;&gt;을 기반으로 구현되어 있지만, &lt;br /&gt;서로 다른 특징을 가지고 있습니다.&lt;/span&gt;&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;패킷(Packet)이란?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;인터넷 내에서 데이터를 보내기 위한 경로배정(라우팅)을 효율적으로 하기 위해서 데이터를 여러 개의 조각들로 나누어 전송을 하는데 이때, 이 조각을 패킷이라고 합니다.&lt;/span&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;span style=&quot;background-color: #ffffff; color: #333333;&quot;&gt;그림을 보면 왼쯕은 TCP, 오른쪽은 UDP입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwYg3U/btrz5ntECIC/P9s4Y3TddxUBcLZ5KB5n31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwYg3U/btrz5ntECIC/P9s4Y3TddxUBcLZ5KB5n31/img.png&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;609&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4118%; margin-right: 10px;&quot; data-widthpercent=&quot;49.99&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwYg3U/btrz5ntECIC/P9s4Y3TddxUBcLZ5KB5n31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwYg3U%2Fbtrz5ntECIC%2FP9s4Y3TddxUBcLZ5KB5n31%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;650&quot; height=&quot;609&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UmQWX/btrz1jleP3b/LKT7Ft8751pWeFCcrBdYi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UmQWX/btrz1jleP3b/LKT7Ft8751pWeFCcrBdYi0/img.png&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;281&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4254%;&quot; data-widthpercent=&quot;50.01&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UmQWX/btrz1jleP3b/LKT7Ft8751pWeFCcrBdYi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUmQWX%2Fbtrz1jleP3b%2FLKT7Ft8751pWeFCcrBdYi0%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;300&quot; height=&quot;281&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;위 그림에서는 tcp는 데이터가 송&amp;middot;수신을 확인하지만, udp는 일방적이다 데이터를 보내는 것을 볼 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;따라서, 신뢰성이 요구되는 애플리케이션에서는 TCP를 사용&lt;span style=&quot;background-color: #ffffff;&quot;&gt;하고,&amp;nbsp;&lt;br /&gt;&lt;/span&gt;간단한 데이터를 빠른 속도로 전송하고자 하는 애플리케이션에서는 UDP를 사용합니다.&lt;/span&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;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;TCP(Transmission Control Protocol)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;TCP은 &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; letter-spacing: 0px;&quot;&gt;인터넷상에서 데이터를 메세지의 형태로 보내기 위해 IP와 함께 사용하는 프로토콜입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;장치들 사이에 논리적인 접속을 성립하기 위해 연결을 설정하여&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;신뢰성을 보장하는 연결형 서비스&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;&lt;span&gt; 입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;[ TCP 특징 ]&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;연결형 서비스로 가상 회선 방식을 제공&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;3-way handshaking과정을 통해 연결을 설정&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;4-way handshaking을 통해 해제&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;흐름 제어 및 혼잡 제어&lt;/span&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;데이터 처리 속도를 조절하여 수신자의 버퍼 오버플로우를 방지&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;정보의 소통량이 과다하면 패킷을 조금만 전송하여 혼잡 붕괴 현상이 일어나는 것을 막는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;높은 신뢰성을 보장&lt;/span&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;Dupack-based retransmission
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정상적인 상황에서는 ACK 값이 연속적으로 전송되어야 함&lt;/li&gt;
&lt;li&gt;그러나 ACK값이 중복으로 올 경우 패킷 이상을 감지하고 재전송을 요청&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Timeout-based retransmission
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일정시간동안 ACK 값이 수신을 못할 경우 재전송을 요청&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;UDP보다 속도가 느림&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;전이중(Full-Duplex), 점대점(Point to Point) 방식&lt;/span&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;전이중 (Full-Duplex)&lt;/b&gt;&lt;br /&gt;전송이 양방향으로 동시에 일어날 수 있음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;점대점 (Point to Point)&lt;/b&gt;&lt;br /&gt;각 연결이 정확히 2개의 종단점을 가지고 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;ack-제어비트&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;ACK 제어비트&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ACK는 송신측에 대하여&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;수신측에서 긍정 응답&lt;/b&gt;으로 보내지는 전송 제어용 캐릭터입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ACK 번호를 사용하여 패킷이 도착했는지 확인하고, 패킷이 잘 도착하지 않으면 재송신을 요구합니다&lt;/p&gt;
&lt;h1&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;UDP(User Datagram Protocol)&lt;/b&gt;&lt;/span&gt;&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;인터넷상에서 서로 정보를 주고받을 때 정보를 보낸다는 신호나 받는다는 신호 절차를&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-829f61ef-5bd4-4f92-bfd9-aef8e34f4202&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;거치지 않고,보내는 쪽에서 일방적으로 데이터를 전달하는 통신 프로토콜입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;또한, &lt;span&gt;데이터를 데이터그램 단위로 처리하는 프로토콜입니다. &lt;br /&gt;&lt;span&gt;데이터그램이란 독립적인 관계를 지니는 패킷이라는 뜻입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;[ UDP 특징 ]&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;비연결형 서비스로 데이터그램 방식을 제공&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;연결을&amp;nbsp;설정하고 해제하는 과정이 존재하지 않습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;정보를 주고 받을 때 정보를 보내거나 받는 신호절차를 거치지 않음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;데이터의 경계를 구분&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;신뢰성이 낮음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;TCP보다 속도가 빠름&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;UDP는 비연결형 서비스이기 때문에,&amp;nbsp; 서로 다른 경로로 독립적으로 &lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;처리합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;패킷에 순서를 부여하여 재조립을 하거나 흐름 제어 또는 &lt;br /&gt;혼잡 제어와 같은 기능도 처리하지 않기에 TCP보다&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;속도가 빠릅니다. &lt;br /&gt;네트워크 부하가 적다는 장점이 있지만 신뢰성있는 데이터의 전송을 보장하지는 못합니다. &lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;따라서, 신뢰성보다는 연속성이 중요한 서비스인 실시간 스트리밍(streaming)에 자주 사용됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;TCP와 UDP의 비교&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;843&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3eynK/btrz7z7HAfg/O2bBFvBzVRyH76fyRJnklK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3eynK/btrz7z7HAfg/O2bBFvBzVRyH76fyRJnklK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3eynK/btrz7z7HAfg/O2bBFvBzVRyH76fyRJnklK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3eynK%2Fbtrz7z7HAfg%2FO2bBFvBzVRyH76fyRJnklK%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;843&quot; height=&quot;377&quot; data-origin-width=&quot;843&quot; data-origin-height=&quot;377&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p id=&quot;SE-01fddceb-6543-4952-b0ee-e395c70082e2&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;TCP는 연속성보다 신뢰성있는 전송이 중요할 때에 사용하는 프로토콜이며,&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-c213f06b-b19d-40ef-afcb-3a2443ef3b82&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;UDP는 TCP보다 속도가 빠르며 네트워크 부하가 적다는 장점이 있지만, 신뢰성있는 데이터 전송을 보장하지는 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p id=&quot;SE-38337708-3643-485a-bca9-99fff8dff8cc&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그렇기 때문에 신뢰성보다는 연속성이 중요한 서비스의 예를 들면 실시간 서비스(streaming)에 자주 사용됩니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Web</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/83</guid>
      <comments>https://oagree0123.tistory.com/entry/TCP-%EC%99%80-UDP-%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%B4-%EB%8B%A4%EB%A5%BC%EA%B9%8C#entry83comment</comments>
      <pubDate>Fri, 22 Apr 2022 09:52:30 +0900</pubDate>
    </item>
    <item>
      <title>css의 position</title>
      <link>https://oagree0123.tistory.com/entry/css%EC%9D%98-postion</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666;&quot;&gt;이번 글에서는 CSS의 position 속성에 대해서 알아보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 id=&quot;position-속성&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;position&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;position&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성은 HTML에서 요소가 배치되는 방식을 결정합니다. &lt;br /&gt;모든 경우는 아니지만, position&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성은 요소의 정확한 위치 지정을 위해서&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;top,&lt;span&gt;&amp;nbsp;&lt;/span&gt;left,&lt;span&gt;&amp;nbsp;&lt;/span&gt;bottom,&lt;span&gt;&amp;nbsp;&lt;/span&gt;right&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성과 함께 많이 사용됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;431&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cH9xfi/btrz3lcvzcY/5YrWd1QhrtRw7coS8lJ6T1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cH9xfi/btrz3lcvzcY/5YrWd1QhrtRw7coS8lJ6T1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cH9xfi/btrz3lcvzcY/5YrWd1QhrtRw7coS8lJ6T1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcH9xfi%2Fbtrz3lcvzcY%2F5YrWd1QhrtRw7coS8lJ6T1%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;660&quot; height=&quot;431&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;431&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id=&quot;position-static&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;position: static&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;position&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성을 별도로 지정해주지 않으면 기본값인&lt;span&gt;&amp;nbsp;&lt;/span&gt;static이 적용됩니다.&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;static은 요소들이 HTML에 작성된 순서대로 브라우저 화면에 표시가 됩니다.&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;top,&lt;span&gt;&amp;nbsp;&lt;/span&gt;left,&lt;span&gt;&amp;nbsp;&lt;/span&gt;bottom,&lt;span&gt;&amp;nbsp;&lt;/span&gt;right&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성값은&lt;span&gt;&amp;nbsp;&lt;/span&gt;position&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성이&lt;span&gt;&amp;nbsp;&lt;/span&gt;static일 때는 무시됩니다.&lt;/p&gt;
&lt;h3 id=&quot;position-static&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;position: relative&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;relative는 요소를&lt;span&gt;&amp;nbsp;&lt;/span&gt;원래 위치를 기준으로 상대적(relative)으로 배치해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 이야기한 top,&lt;span&gt;&amp;nbsp;&lt;/span&gt;bottom,&lt;span&gt;&amp;nbsp;&lt;/span&gt;left,&lt;span&gt;&amp;nbsp;&lt;/span&gt;right&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성을 이용해서, &lt;br /&gt;요소가 원래 위치에 있을 때의 상하좌우로 부터 얼마나 떨어지게 할지를 지정할 수 있습니다.&lt;/p&gt;
&lt;h3 id=&quot;position-static&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;position: absolute&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;absolute는&lt;span style=&quot;background-color: #ffffff; color: #1b2e46;&quot;&gt; 배치 기준이 상황에 따라 다르게 적용되고 요소의 위치를 배치시킵니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;absolute&lt;span style=&quot;background-color: #ffffff; color: #1b2e46;&quot;&gt;일 때 해당 요소는 배치 기준을 자신이 아닌 상위 요소에서 찾습니다. &lt;br /&gt;DOM 트리를 따라 올라가다가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;position&lt;span style=&quot;background-color: #ffffff; color: #1b2e46;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;static&lt;span style=&quot;background-color: #ffffff; color: #1b2e46;&quot;&gt;이 아닌 첫 번째 상위 요소가 해당 요소의 배치 기준으로 설정됩니다. 만약에 해당 요소 상위에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;position&lt;span style=&quot;background-color: #ffffff; color: #1b2e46;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성이&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;static&lt;span style=&quot;background-color: #ffffff; color: #1b2e46;&quot;&gt;이 아닌 요소가 없다면, DOM 트리에 최상위에 있는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;lt;body&amp;gt;&lt;span style=&quot;background-color: #ffffff; color: #1b2e46;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;요소가 배치 기준이 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;position-static&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;position:&lt;span&gt; fixed&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fixed는 요소를 항상 고정된(fixed) 위치에 배치할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fixed의 배치 기준은 자신이나 부모 요소가 아닌 뷰포트(viewport) 입니다.&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;top,&lt;span&gt;&amp;nbsp;&lt;/span&gt;left,&lt;span&gt;&amp;nbsp;&lt;/span&gt;bottom,&lt;span&gt;&amp;nbsp;&lt;/span&gt;right&lt;span&gt; 속성을 통해 브라우저의 위치로 부터 상하자와에 얼마나 떨어져 있는지를 경정합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 id=&quot;position-static&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;position:&lt;span&gt; sticky&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;sticky는 css에서 비교적 최근에 추가된 속성입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #3b454e;&quot;&gt;sitcky로 설정된 영역은 설정된 위치에 도달하기 전까지는 static 속성처럼 행동하다가&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;설정된 위치&lt;span style=&quot;color: #3b454e;&quot;&gt;에 다다르면 fixed 속성처럼 행동하는 속성입니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Web</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/82</guid>
      <comments>https://oagree0123.tistory.com/entry/css%EC%9D%98-postion#entry82comment</comments>
      <pubDate>Fri, 22 Apr 2022 00:37:21 +0900</pubDate>
    </item>
    <item>
      <title>[React] 렌더링 성능 개선하기</title>
      <link>https://oagree0123.tistory.com/entry/React-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%84%B1%EB%8A%A5-%EA%B0%9C%EC%84%A0%ED%95%98%EA%B8%B0</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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴포넌트의 state가 변경되었을 때&lt;/li&gt;
&lt;li&gt;부모 컴포넌트에서 받은 props가 변경될 때&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;p data-ke-size=&quot;size16&quot;&gt;부모 컴포넌트의 state가 바뀌면 props를 받은 자식 컴포넌트와 &lt;br /&gt;변경된 state를 받지 않은 자식 컴포넌트 모두 렌더링 됩니다.&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;이러한 불필요한 렌더링을 줄이고 성능을 높이는 방법을 설명하겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;useMemo&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useMemo는 React에서 CPU 소모가 심한 함수들을 캐싱하기 위해 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useMemo를 사용하면 복잡한 계산식의 계산한 값을 재사용할 수 있습니다.&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;리렌더링될 때마다 함수가 호출되면서 많은 시간을 소요하게 될 것입니다.&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;pre id=&quot;code_1650281328904&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useState, useMemo, useRef } from &quot;react&quot;;
import Item from &quot;./Item&quot;;
import Average from &quot;./Average&quot;;

function UserList() {
  const [users, setUsers] = useState([
    {
      id: 0,
      name: &quot;gildong&quot;,
      age: 24,
      score: 100
    },
    {
      id: 1,
      name: &quot;chulsu&quot;,
      age: 28,
      score: 10
    }
  ]);

  const cal_average = (() =&amp;gt; {
    console.log(&quot;시간이 오래걸려요!!!&quot;);
    return users.reduce((acc, cur) =&amp;gt; {
      return acc + cur.age / users.length;
    }, 0);
  })();

  return (
      &amp;lt;div&amp;gt;
       	&amp;lt;Average average={cal_average} /&amp;gt;
      &amp;lt;/div&amp;gt;
  );
}

export default UserList;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Average 컴포넌트를 보면 cal_average함수가 실행되면, 리턴 값이 props로 전달되는 것을 볼 수 있습니다.&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;UserList 컴포넌트가 리렌더링 될 때마다 매번 연산을 수행해야 합니다.&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;이때, useMemo를 사용하면 데이터가 변했을 경우에만 cal_average함수를 수행하도록 할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1650282794531&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;useMemo(()=&amp;gt; function, [input_dependency]) //useMemo 기본 형태

const cal_average = useMemo(() =&amp;gt; {
   console.log(&quot;시간이 오래걸려요!!!&quot;);
   return users.reduce((acc, cur) =&amp;gt; {
     return acc + cur.score / users.length;
   }, 0);
 }, [users]);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 보면 input_dependency에 state를 넣어주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useMemo는 input_dependency의 값이 변하지 않을 경우 다시 함수를 호출하지 않고, 이전에 리턴 값을 재사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 함수 호출 시간을 줄여줄 것이고, 자식 컴포넌트의 리렌더링도 방지해 줄 것입니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;React.memo 컴포넌트 메모이제이션&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;React.memo는 렌더링 결과를 메모이제이션 합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;컴포넌트의 props가 바뀌지 않았다면, 리렌더링이 일어나지 않도록 설정하여&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;함수형 컴포넌트의 렌더링 성능을 최적화할 수 있습니다.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;또한, 콜백함수를 이용하여 메모이제이션을 적용하는지에 대한 여부를 파악할 수 있습니다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1650292714071&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//UserList.jsx
import { useState, useRef } from &quot;react&quot;;
import Item from &quot;./Item&quot;;
import Average from &quot;./Average&quot;;

function UserList() {
  let numberRef = useRef(0);
  const [text, setText] = useState(&quot;&quot;);
  const [users, setUsers] = useState([
    {
      id: 0,
      name: &quot;gildong&quot;,
      age: 24,
      score: 100
    },
    {
      id: 1,
      name: &quot;chulsu&quot;,
      age: 28,
      score: 10
    }
  ]);

  const cal_average = useMemo(() =&amp;gt; {
    console.log(&quot;시간이 오래걸려요!!&quot;);
    return users.reduce((acc, cur) =&amp;gt; {
      return acc + cur.score / users.length;
    }, 0);
  }, [users]);
  
   const add_user =() =&amp;gt; {
    setUsers([
      ...users,
      {
        id: (numberRef.current += 1),
        name: &quot;yeonkor&quot;,
        age: 30,
        score: 90
      }
    ]);
  }

  return (
      &amp;lt;div&amp;gt;
       &amp;lt;input
         type=&quot;text&quot;
         value={text}
         placeholder=&quot;내용을 입력하세요.&quot;
         onChange={(event) =&amp;gt; setText(event.target.value)}
        /&amp;gt;
       &amp;lt;Average average={cal_average} /&amp;gt;
       &amp;lt;button className=&quot;button&quot; onClick={add_user}&amp;gt;
        새 유저 생성
       &amp;lt;/button&amp;gt;
      {users.map((user) =&amp;gt; {
        return (
          &amp;lt;Item key={user.id} user={users} /&amp;gt;
        );
      })}
      &amp;lt;/div&amp;gt;
  );
}

export default UserList;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1650294884240&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//Item.jsx
import React,{ memo } from &quot;react&quot;;

function Item({ user }) {
  console.log(&quot;Item component render&quot;);

  return (
    &amp;lt;div className=&quot;item&quot;&amp;gt;
      &amp;lt;div&amp;gt;이름: {user.name}&amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;나이: {user.age}&amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;점수: {user.score}&amp;lt;/div&amp;gt;
      &amp;lt;div&amp;gt;등급: {result.grade}&amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default memo(Item);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;위 코드에서는 Item 컴포넌트에 React.memo로 감싸 사용하였습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;이는 버튼을 누르면 users 배열의 값이 추가되고 &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;UserList 컴포넌트가 리렌더링 되더라도, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;새로 추가된 Item 컴포넌트만 새로 렌더링 되고 이미 존재하던 Item 컴포넌트가 리렌더링 되지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;useCallback&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;useCallback은 함수 선언을 메모이제이션 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt; 메모이제이션된 함수는 dependency에 담긴 state가 변경되었을 때에만 변경된다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;또한, 콜백 안에서 참조되는 모든 state는&amp;nbsp;&lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;dependency&lt;/span&gt;에 나타나야 합니다.&lt;/span&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;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;위 코드의 버튼을 아래의 컴포넌트로 바꿔보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1650293333001&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Button.jsx
import React.{memo} from &quot;react&quot;;

function Button({ onClick }) {
    console.log(&quot;Button component render&quot;);

  return (
    &amp;lt;button type=&quot;button&quot; onClick={onClick}&amp;gt;
      버튼
    &amp;lt;/button&amp;gt;
  );
}

export default memo(Button);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;onClick 함수는 UserList 컴포넌트에서 props로 받고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 React.memo 에서 본 것 처럼 &lt;span style=&quot;background-color: #f8f9fa; color: #212529;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;onClick props가 동일한지 체크한 후 동일하다면 리렌더링 되지 않아야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #212529;&quot;&gt;그런데, 위의 코드에서는 리렌더링이 일어납니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #212529;&quot;&gt;그 이유는 &lt;b&gt;함수는 객체&lt;/b&gt;이고, &lt;b&gt;새로 생성된 함수는 다른 참조 값&lt;/b&gt;을 가지고 있어&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #212529;&quot;&gt;Button 컴포넌트에서는 새로 생성된 함수를 받을 때 props가 변한 것으로 파악합니다.&lt;/span&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;useCallback&lt;/b&gt;을 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;useCallback으로 함수를 선언하면, dependency가 변하지 않는 이상 함수를 재생성하지 않고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 참조 값을 props로 전달하여 props가 변하지 않도록 파악하게 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1650293832456&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const add_user = useCallback(() =&amp;gt; {
    setUsers([
      ...users,
      {
        id: (numberRef.current += 1),
        name: &quot;yeonkor&quot;,
        age: 30,
        score: 90
      }
    ]);
  }, [users]);&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;b&gt;정리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;useMemo&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 계산이 오래걸리는 복잡한 함수나 지속적으로 업데이트 되는 onChange같은 함수를 캐싱하는데 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;React.memo&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- props를 받는 자식 컴포넌트는 React.memo로 감싸서 생성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;React.memo는 렌더링 결과를 메모이제이션하여 props가 바뀌지 않으면 리렌더링 되지 않게 합니다.&lt;/span&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;useCallback&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;span style=&quot;background-color: #ffffff; color: #555555;&quot;&gt;useCallback은 함수 선언을 메모이제이션 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- props로 함수를 전달할 때, &lt;br /&gt;&amp;nbsp; useCallback으로 함수를 선언하면 dependency가 변하지 않는 이상 함수를 재생성하지 않고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 이전에 참조 값을 props로 전달하여 props가 변하지 않도록 파악하게 합니다.&lt;/p&gt;</description>
      <category>React</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/81</guid>
      <comments>https://oagree0123.tistory.com/entry/React-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%84%B1%EB%8A%A5-%EA%B0%9C%EC%84%A0%ED%95%98%EA%B8%B0#entry81comment</comments>
      <pubDate>Tue, 19 Apr 2022 00:14:55 +0900</pubDate>
    </item>
    <item>
      <title>async/await은 왜 쓰는가?</title>
      <link>https://oagree0123.tistory.com/entry/asyncawait%EC%9D%80-%EC%99%9C-%EC%93%B0%EB%8A%94%EA%B0%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;이번 글에서는 Promise와 async/await의 차이에 대해서 공부해보겠습니다!&lt;/span&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;span style=&quot;color: #666666;&quot;&gt;더 자세하게 내용을 작성했습니다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://oagree0123.tistory.com/entry/asyncawait%EC%9D%80-%EC%99%9C-%EC%93%B0%EB%8A%94%EA%B0%80-JS-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.05.02 - [JavaScript] - async/await은 왜 쓰는가? : JS 비동기 처리하기&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;동기 / 비동기 특징&lt;/b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동기의 (대략적인) 특징
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동시에 여러 작업을 수행할 수 &lt;b&gt;없다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;흐름을 예측하기 쉽다. 먼저 수행되고 나중에 수행되는 것들이 명확하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;비동기의 (대략적인) 특징
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;동시에 여러 작업을 수행할 수&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;있다&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;흐름을 예측하기 어렵다. (무엇이 먼저 완료될 지 보장할 수 없다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Promise&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;Promise&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;는 자바스크립트에서 비동기 처리에 사용되는 객체입니다.&lt;/span&gt;&lt;br /&gt;코드는 실행 되었지만 결과를 아직 반환하지 않은 객체&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;라고 설명할 수 있습니다.&lt;/span&gt;&lt;/span&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;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;Promise는 3가지 상태가 있습니다.&lt;/span&gt;&lt;/span&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;b&gt;Pending&lt;/b&gt;(대기)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Fulfilled&lt;/b&gt;(이행)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Rejected&lt;/b&gt;(실패)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 처리를 아직 수행하는 단계인 Pending, &lt;br /&gt;비동기 처리가 완료되어 값을 반환한 상태인 Fulfilled,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666;&quot;&gt;비동기 처리가 어떠한 이유에서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #666666;&quot;&gt;실패한 상태 Rejected,&lt;/span&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;&lt;b&gt;Promise의 사용 코드&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1650259728003&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const condition = true;
const promise = new Promise((resolve, reject) =&amp;gt; {
  if (condition) {
    resolve('resolved');
  } else {
    reject('rejected');
  }
});

promise
  .then((res) =&amp;gt; {
    console.log(res);
  })
  .catch((error) =&amp;gt; {
    console.error(error);
  });&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 보면, promise라는 변수에 Promise 생성자 함수를 사용하여 할당하는 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 생성자 함수는 &lt;b&gt;executor&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;&lt;span&gt;&lt;span&gt; 라고 불리는&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; 특별함 함수(함수의 형태는 화살표 함수) 하나를 인자로 받습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;executor 함수는 resolve와 reject 라는 두 가지 인수를 받는데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;resolve를 호출하게 된다면 비동기 작업의 성공을 의미하고, reject를 호출하면 실패를 의미합니다.&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;b&gt;Promise의 동작 처리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise가 끝난 후 동작을 설정할 수 있는데, 이는 &lt;b&gt;then메소드&lt;/b&gt;와 &lt;b&gt;catch메소드&lt;/b&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드는 성공하도록 만들었기 때문에 resolve를 호출되기 때문에, then메소드의 동작만 실행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, reject가 호출되면 catch메소드의 동작만 실행됩니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;async / await&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;async/await은 &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Promise&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;와 굉장히 밀접한 연관을 가지고 있는데, &lt;br /&gt;&lt;/span&gt;executor에&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;&amp;nbsp;몇 가지 규칙만 적용한다면&lt;span&gt; &lt;/span&gt;&lt;/span&gt;Promise 객체를&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;&amp;nbsp;리턴하는 함수를&lt;span&gt; &lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;async/await&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;로 변환할 수 있습니다.&lt;/span&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;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;async&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;async 키워드는 함수를 선언할 때 붙여줄 수 있습니다.&lt;br /&gt;&lt;/span&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;span&gt;&amp;nbsp;&lt;/span&gt;async&lt;span&gt;&amp;nbsp;&lt;/span&gt;키위드를 붙이고, Promise 생성자 함수를 제거합니다.&lt;/li&gt;
&lt;li&gt;resolve(value); 를&lt;span&gt;&amp;nbsp;&lt;/span&gt;return value;&lt;span&gt;&amp;nbsp;&lt;/span&gt;로 변경합니다.&lt;/li&gt;
&lt;li&gt;reject(error);&lt;span&gt;&amp;nbsp;&lt;/span&gt;부분을&lt;span&gt;&amp;nbsp;&lt;/span&gt;throw new Error();&lt;span&gt;&amp;nbsp;&lt;/span&gt;로 수정합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;await&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;await은&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt; Promise가 fulfilled 또는 rejected이 될 때까지 기다리는 함수입니다&lt;/span&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;pre id=&quot;code_1650262894413&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;(async () =&amp;gt; {
  const condition = true;
  const promise = new Promise((resolve, reject) =&amp;gt; {
    if (condition) {
      resolve('resolved');
    } else {
      reject('rejected');
    }
  });

  try {
    const result = await promise;
    console.log(result);
  } catch (err) {
    console.error(err);
  }
})();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;Promise를 사용했던 코드를 익명 함수에 async/await&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;를 사용하였습니다.&lt;/span&gt;&lt;br /&gt;async&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;&lt;span&gt; 익명&amp;nbsp;&lt;/span&gt;함수의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;await으로&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;&amp;nbsp;&lt;/span&gt;Promise&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;의 반환 값을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;result&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;변수에 담아 출력하는 예제입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;여기서는 Promise와 다르게 try-catch()문으로 동작을 처리하는 것을 볼 수 있습니다.&lt;/span&gt;&lt;/span&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;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;왜 async/await을 쓸까 ?&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;1. async는 에러 위치를 찾기 쉽습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, Promise를 여러번 호출해야하는 경우가 생긴다고 한다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 then메소드에서 오류가 났는지 확인하기 어렵습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1650264643025&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function sample() {
  return sampleFunc()
    .then(data =&amp;gt; return data)
    .then(data2 =&amp;gt; return data2)
    .then(data3 =&amp;gt; return data3)
    .catch(err =&amp;gt; console.log(err))  // 결과적으로 문제가 발생했다
}

async function sample() {
  const data1 = await sampleFunc();      // 문제 발생시 data1값이 유효치 않음
  const data2 = await sampleFunc2(data1);
  return data2;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;2. async 코드는 가독성이 좋습니다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 코드를 보면 then에 비해 async를 사용했을 때, 짧아지는 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 리턴값을 변수에 담아 사용하므로 직관적으로 변수를 인식할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1650264242372&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function printAnimals() {
  return getAnimals()
    .then(data =&amp;gt; {
      if (data.property) {
        return sampleFunc1(data)
          .then(anotherData =&amp;gt; {
            console.log(anotherData)
          })
      }else {
        console.log(data)
      }
    })
}

async function printAnimals() {
  const animals = await getAnimals();
  if (animals.property) {
    const sampleData = await sampleFunc1(animals);
    console.log(sampleData);
  }else {
    console.log(animals);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #242433;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;3. async는 에러 핸들링에 유리합니다.&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;이번에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;printAnimals()&lt;span style=&quot;color: #666666;&quot;&gt;에서 에러가 발생한 게 아니라,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;JSON.parse&lt;span style=&quot;color: #666666;&quot;&gt;에서 에러가 발생했다고 가정합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 경우에는 try-catch()문을 사용했음에도, then메소드를 사용하여 catch문을 추가로 작성해야 합니다.&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;그러나 async를 사용하게 되면 try-catch문 하나로 처리할 뿐만 아니라, &lt;br /&gt;직관적으로 어디서 오류가 났는지 파악할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1650264382110&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function printAnimals() {
  try {
      getAnimals()
      .then((response) =&amp;gt; {
      const data = JSON.parse(response); // 여기서 에러 발생한다고 가정
      console.log(data);
    })
    .catch((err)=&amp;gt; {   // 추가적인 에러
      console.log(err)
    })
  }
  catch(err) {
    console.log(err)
  }
}

async function printAnimals() {
  try {
    const data = await JSON.parse((getAnimals())
    console.log(data);
  }
  catch(err) {
    console.log(err)
  }
}&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;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;&amp;nbsp;&lt;/p&gt;</description>
      <category>JavaScript</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/80</guid>
      <comments>https://oagree0123.tistory.com/entry/asyncawait%EC%9D%80-%EC%99%9C-%EC%93%B0%EB%8A%94%EA%B0%80#entry80comment</comments>
      <pubDate>Mon, 18 Apr 2022 15:52:27 +0900</pubDate>
    </item>
    <item>
      <title>[Back&amp;amp;Stock] 피드백 반영하기</title>
      <link>https://oagree0123.tistory.com/entry/BackStock-%ED%94%BC%EB%93%9C%EB%B0%B1-%EB%B0%98%EC%98%81%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;이 글은 항해99 마지막 실전 프로젝트를 끝내면서 정리하는 글입니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 실제 서비스를 하면서 설문조사 피드백을 받고 반영했던 &lt;br /&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;&lt;b&gt;긍정적 피드백&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 설문에서 프로젝트에 대해 긍정적인 부분이라고 답해주셨던 부분은 &lt;b&gt;UI &lt;/b&gt;였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무엇보다 깔끔한 UI가 보기 편하고 필요한 요소들만 있는 것 같다는 피드백이 있었다.&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;&lt;b&gt;처음 접하는 사람에게 설명하기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설문 피드백을 보았을 때, 위의 긍정적 피드백과 상반되게&lt;br /&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;br /&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;이 문제에 대해 2가지 방법을 사용하여 피드백을 반영했다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 실험 방법 추가하기&lt;/b&gt;&lt;/h4&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;실험 방법 버튼을 헤더에 만들었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brNagl/btry32W519r/7y4sGENGr38qiDl6AMdeI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brNagl/btry32W519r/7y4sGENGr38qiDl6AMdeI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brNagl/btry32W519r/7y4sGENGr38qiDl6AMdeI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrNagl%2Fbtry32W519r%2F7y4sGENGr38qiDl6AMdeI1%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;482&quot; height=&quot;278&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;490&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 실시간 문구와 alert 창&lt;/b&gt;&lt;/h4&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;이에 대해, 사용자에게 실시간으로 알려주는 문구나 어떠한 이유 때문에 실험을 시작할 수 없는지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알려주는 alert 창을 만들었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dbyQNH/btry0clVGbt/mpLluXqhUvk0khUJmxphZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dbyQNH/btry0clVGbt/mpLluXqhUvk0khUJmxphZ0/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;564&quot; data-origin-height=&quot;327&quot; data-filename=&quot;그림3.png&quot; style=&quot;width: 46.5893%; margin-right: 10px;&quot; data-widthpercent=&quot;47.14&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dbyQNH/btry0clVGbt/mpLluXqhUvk0khUJmxphZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdbyQNH%2Fbtry0clVGbt%2FmpLluXqhUvk0khUJmxphZ0%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;564&quot; height=&quot;327&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/M2PVo/btryUe6yung/MKu1OUE305YlUQ4lptvwa1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/M2PVo/btryUe6yung/MKu1OUE305YlUQ4lptvwa1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;559&quot; data-origin-height=&quot;289&quot; data-filename=&quot;그림2.png&quot; style=&quot;width: 52.2479%;&quot; data-widthpercent=&quot;52.86&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/M2PVo/btryUe6yung/MKu1OUE305YlUQ4lptvwa1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FM2PVo%2FbtryUe6yung%2FMKu1OUE305YlUQ4lptvwa1%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;559&quot; height=&quot;289&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&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;&lt;b&gt;피드백에 대한 이후 계획&lt;/b&gt;&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;br /&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;&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;지금 사이트는 다양한 정보나 차트 때문에 모바일에 대한 뷰를 포기했지만,&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;&lt;b&gt;느낀점&lt;/b&gt;&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;사용자의 대한 행동에 대해서 더 자세하고 섬세하게 고려해야 한다는 것이었다.&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;사용자들은 한 번에 모든 것을 파악하는 사람은 없으며 &lt;br /&gt;이에 대해 자세하고 꼼꼼하게 알려주어야 한다는 것을 알았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 이러한 작은 것이지만 필수적인 요소들이 사용자의 경험에 많은 영향을 끼치고 있다는 것을 느꼈다.&lt;/p&gt;</description>
      <category>React</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/79</guid>
      <comments>https://oagree0123.tistory.com/entry/BackStock-%ED%94%BC%EB%93%9C%EB%B0%B1-%EB%B0%98%EC%98%81%ED%95%98%EA%B8%B0#entry79comment</comments>
      <pubDate>Sun, 10 Apr 2022 23:24:45 +0900</pubDate>
    </item>
    <item>
      <title>[Back&amp;amp;Stock] 컴포넌트는 무엇일까?</title>
      <link>https://oagree0123.tistory.com/entry/React-BackStock-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EC%A0%95%EB%A6%AC%ED%95%98%EB%8A%94-%EA%B8%80-1</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;이 글은 항해99 마지막 실전 프로젝트를 끝내면서 정리하는 글입니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;프로젝트를 진행하면서 짧은 시간안에 기획부터 UI, 기능 모두 완성해야 한다는 것이&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;컴포넌트 중요성&lt;/b&gt;&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;그렇기 때문에 컴포넌트를 처음부터 잘 만드는 것이 하나의 프로젝트를 완성하는데&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;라인 차트, 바 차트, 달력, 포트폴리오의 리스트와 포트폴리오 카드 하나 등 어떠한&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;컴포넌트의 재사용성&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식이 하나의 컴포넌트가 하나의 기능을 하기 때문에 편리하고 &lt;br /&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&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFXTvG/btryEtuWq4Y/OkUuJ2T3eyvsL8CB0BNf11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFXTvG/btryEtuWq4Y/OkUuJ2T3eyvsL8CB0BNf11/img.png&quot; data-origin-width=&quot;392&quot; data-origin-height=&quot;280&quot; data-is-animation=&quot;false&quot; data-filename=&quot;blob&quot; width=&quot;379&quot; height=&quot;271&quot; style=&quot;width: 53.8382%; margin-right: 10px;&quot; data-widthpercent=&quot;54.47&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFXTvG/btryEtuWq4Y/OkUuJ2T3eyvsL8CB0BNf11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFXTvG%2FbtryEtuWq4Y%2FOkUuJ2T3eyvsL8CB0BNf11%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;392&quot; height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFpoqa/btryF8wOrKg/eg6D2Odrukj27HmBlgUPxk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFpoqa/btryF8wOrKg/eg6D2Odrukj27HmBlgUPxk/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;784&quot; data-origin-height=&quot;670&quot; data-filename=&quot;blob&quot; data-widthpercent=&quot;45.53&quot; style=&quot;width: 44.9991%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFpoqa/btryF8wOrKg/eg6D2Odrukj27HmBlgUPxk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFpoqa%2FbtryF8wOrKg%2Feg6D2Odrukj27HmBlgUPxk%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;784&quot; height=&quot;670&quot;/&gt;&lt;/span&gt;&lt;/div&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;이후 결과 페이지에서 바로 실험 결과를 수정할 수 있도록 기획이 추가되었을 때,&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;다음 프로젝트에서는 ?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 프로젝트에서는 더 작은 컴포넌트를 나눠서 작업해 보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코딩을 하면서 Button이나 Input 같은 요소들이 반복되는 것을 느꼈고,&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;조금씩 달라지는 것들은 props로 전달해 주면 되니까 : &amp;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;다음 글에서는 useState, useEffect에 대해서 작성해보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두놈 때문에 골머리좀 썩었던 일에 대해 써볼거다!!!!&lt;/p&gt;</description>
      <category>React</category>
      <category>리액트</category>
      <category>컴포넌트</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/78</guid>
      <comments>https://oagree0123.tistory.com/entry/React-BackStock-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%A5%BC-%EC%A0%95%EB%A6%AC%ED%95%98%EB%8A%94-%EA%B8%80-1#entry78comment</comments>
      <pubDate>Thu, 7 Apr 2022 00:24:22 +0900</pubDate>
    </item>
    <item>
      <title>[항해99] 12주차 회고</title>
      <link>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-12%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;한 주에 대한 정리&lt;/b&gt;&lt;/h4&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;커뮤니티에도 글을 쓰며 홍보를 했습니다.&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;사용자는 내 생각보다 훨씬 다양한 유형으로&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;이 외에도 많은 버그나, 사용성에서 불편한 점들의 피드백을 받았습니다.&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;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/77</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-12%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0#entry77comment</comments>
      <pubDate>Mon, 4 Apr 2022 00:25:51 +0900</pubDate>
    </item>
    <item>
      <title>[항해99] 11주차 회고</title>
      <link>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-11%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;한 주에 대한 정리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;11주차는 개발을 정리하고 조금 더 완성도 있게&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;배포는 s3, cloudfront, route53으로 진행했고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;github action으로 무중단 배포를 구현했습니다.&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;걱정되면서 기대되는 것같습니다.&lt;/p&gt;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/76</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-11%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0#entry76comment</comments>
      <pubDate>Mon, 28 Mar 2022 00:29:04 +0900</pubDate>
    </item>
    <item>
      <title>[항해99] 10주차 회고</title>
      <link>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-10%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;한 주에 대한 정리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10주차는 mvp를 개발하여&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;구현에 초점을 맞춰 개발하는데 집중했습니다.&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;프로젝트나 코드에 대해 전반적인 피드백을 주시는 멘토님도 있으셨습니다.&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;개발을 진행하려고 합니다.!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/75</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-10%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0#entry75comment</comments>
      <pubDate>Mon, 21 Mar 2022 00:46:33 +0900</pubDate>
    </item>
    <item>
      <title>[항해99] 9주차 회고</title>
      <link>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-8%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0-1</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;한 주에 대한 정리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번주에 이어서 이번주도 실전 프로젝트를 진행중입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번주는 드디어 기획이 끝나고 vscode를 사용할 수 있는 날이었습니다.&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;프로젝트를 잘진행하기 위해서는 기획, 디자인, 백엔드 모두 고려해야하고&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;중요하다고 생각하는 부분이 달라 다양한 요소들을 맞춰가는 것에 있어&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;프로젝트가 조금씩 나아진다는 것을 알 수 있었습니다.&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/74</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-8%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0-1#entry74comment</comments>
      <pubDate>Sun, 13 Mar 2022 19:39:57 +0900</pubDate>
    </item>
    <item>
      <title>[항해99] 8주차 회고</title>
      <link>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-8%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;한 주에 대한 정리&lt;/b&gt;&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; vscode를 거의 켜지 못하고 프로젝트를&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;느껴진다는 피드백이 있어 기획을 바꾸게 되었고&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;p data-ke-size=&quot;size16&quot;&gt;코딩에 집중할 수 있었으면 좋겠습니다.&lt;/p&gt;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/73</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-8%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0#entry73comment</comments>
      <pubDate>Sun, 6 Mar 2022 21:12:03 +0900</pubDate>
    </item>
    <item>
      <title>[React: code] 리덕스는 어떻게 사용할까?</title>
      <link>https://oagree0123.tistory.com/entry/React-code-%EB%A6%AC%EB%8D%95%EC%8A%A4-%EC%82%AC%EC%9A%A9-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;이 글의 목적은 제가 작성한&amp;nbsp; 코드를 다시 되집어 보는데 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트를 진행하면서 리액트의 리덕스를 어떠한 순서로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용하여 CRUD를 구현하였는지 다시 보고 정리하는 글입니다.&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;사용한 주요 패키지는 아래와 같고, firebase를 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- react-redux&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- redux-action&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- redux-thunk&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- immer&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;먼저, 리덕스를 살펴보면,&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;374&quot; data-origin-height=&quot;298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/W1ofu/btruE7WDl6I/YI6oL5dJvlXIIZfRRlHmA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/W1ofu/btruE7WDl6I/YI6oL5dJvlXIIZfRRlHmA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/W1ofu/btruE7WDl6I/YI6oL5dJvlXIIZfRRlHmA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FW1ofu%2FbtruE7WDl6I%2FYI6oL5dJvlXIIZfRRlHmA1%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;374&quot; height=&quot;298&quot; data-origin-width=&quot;374&quot; data-origin-height=&quot;298&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;스토어 - 데이터가 저장되는 곳&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;액션 - 컴포넌트에서 데이터를 변경하여 스토어에 전송하고 싶을 때 선언하는 객체&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;리덕스의 흐름&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) 리덕스 스토어를 컴포넌트가 구독하여 값을 받습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 컴포넌트에서 상태를 변경위해 액션을 선언합니다&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;4) 변경된 상태 값을 스토어에 저장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5) 컴포넌트는 변경된 상태 값을 다시 받아옵니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;미들웨어&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제, 리덕스의 흐름을 알아봤으니 미들웨어에 대해서 간단하게 정리하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;span&gt;미들웨어는&amp;nbsp;&lt;/span&gt;액션을 디스패치했을 때 리듀서에서 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;이를 처리하기에 앞서 사전에 지정된 작업을 실행할 수 있게 해줍니다.&lt;/span&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;span style=&quot;color: #666666;&quot;&gt;프로젝트에서는 redux-thunk를 사용했습니다.&lt;/span&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 alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;208&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDQMiS/btruMnxMgIC/xgpmEp8fNvM4AGh9acxbCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDQMiS/btruMnxMgIC/xgpmEp8fNvM4AGh9acxbCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDQMiS/btruMnxMgIC/xgpmEp8fNvM4AGh9acxbCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDQMiS%2FbtruMnxMgIC%2FxgpmEp8fNvM4AGh9acxbCk%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;473&quot; height=&quot;208&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;208&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;이제 코드에서 어떤 순서로 사용되는지 보겠습니다.&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;1) 컴포넌트에서 디스패치로 액션을 일으킵니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;289&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uVtTs/btruHwJgNwE/IiCsBvuhiBVHxVcQ4e9MO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uVtTs/btruHwJgNwE/IiCsBvuhiBVHxVcQ4e9MO1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uVtTs/btruHwJgNwE/IiCsBvuhiBVHxVcQ4e9MO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuVtTs%2FbtruHwJgNwE%2FIiCsBvuhiBVHxVcQ4e9MO1%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;530&quot; height=&quot;289&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;289&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 보면 useSelector로 스토어의 상태 값을 조회하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 useEffect 안을 보면 dispatch(postActions.getPostFB())가 있는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 설명한 디스패치로 액션을 일으키고 getPostFB라는 미들웨어를 실행시키는 것을 볼 수 있습니다.&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;2) 미들웨어&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/16wdB/btrutlat7rZ/ksdSCJ1FOgg30T8ioEING0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/16wdB/btrutlat7rZ/ksdSCJ1FOgg30T8ioEING0/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;613&quot; data-origin-height=&quot;565&quot; data-filename=&quot;blob&quot; data-widthpercent=&quot;53.07&quot; style=&quot;width: 52.4522%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/16wdB/btrutlat7rZ/ksdSCJ1FOgg30T8ioEING0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F16wdB%2Fbtrutlat7rZ%2FksdSCJ1FOgg30T8ioEING0%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;613&quot; height=&quot;565&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZfnMV/btrurx93lld/eKg8sX5AptQuR6BKJL6NzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZfnMV/btrurx93lld/eKg8sX5AptQuR6BKJL6NzK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;497&quot; data-origin-height=&quot;518&quot; data-filename=&quot;blob&quot; data-widthpercent=&quot;46.93&quot; style=&quot;width: 46.385%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZfnMV/btrurx93lld/eKg8sX5AptQuR6BKJL6NzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZfnMV%2Fbtrurx93lld%2FeKg8sX5AptQuR6BKJL6NzK%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;497&quot; height=&quot;518&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 미들웨어는 firebase에 저장된 post 데이터들을 가져와 action creator로 데이터를 보내줍니다.&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;3) action &amp;amp; action creator&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;307&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjqEpR/btruHwP4bIe/Ob4INivZ94KNEvX0w3Ssyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjqEpR/btruHwP4bIe/Ob4INivZ94KNEvX0w3Ssyk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjqEpR/btruHwP4bIe/Ob4INivZ94KNEvX0w3Ssyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjqEpR%2FbtruHwP4bIe%2FOb4INivZ94KNEvX0w3Ssyk%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;626&quot; height=&quot;307&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;307&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;action이후 리듀서에서 값을 변경 시킵니다.&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&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;745&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0zob2/btruHx9hSrK/QkvITare5sComK7gkZ2rn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0zob2/btruHx9hSrK/QkvITare5sComK7gkZ2rn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0zob2/btruHx9hSrK/QkvITare5sComK7gkZ2rn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0zob2%2FbtruHx9hSrK%2FQkvITare5sComK7gkZ2rn1%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;596&quot; height=&quot;745&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;596&quot; data-origin-height=&quot;745&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리듀서에서는 immer를 사용하여, &lt;span style=&quot;background-color: #ffffff;&quot;&gt;배열이나 객체를 업데이트 해야 할 때에 불변성을 지켜주었습니다.&lt;/span&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;span style=&quot;background-color: #ffffff;&quot;&gt;위에서 코드로 설명한 것이 어떠한 코드인지 정확히 설명하지 않아 이해하기 힘드시겠지만,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;어떠한 흐름으로 리듀서가 작성되는지 파악하시면 좋을 것 같습니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>React</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/71</guid>
      <comments>https://oagree0123.tistory.com/entry/React-code-%EB%A6%AC%EB%8D%95%EC%8A%A4-%EC%82%AC%EC%9A%A9-%ED%9A%8C%EA%B3%A0#entry71comment</comments>
      <pubDate>Tue, 1 Mar 2022 01:32:55 +0900</pubDate>
    </item>
    <item>
      <title>[항해99] 7주차 회고</title>
      <link>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-7%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;한 주에 대한 정리&lt;/b&gt;&lt;/h4&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;화면의 구성이 거의 똑같도록 만드는 것이었습니다.&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;기술적으로 집중한 부분은 redux를 사용하는 것 이었습니다.&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;처음에는 장바구니에 담은 물품들만 redux의 스토어에 저장하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장바구니에서 각 물품의 수량을 useState로 관리하니 오류가 발생했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하고자, redux로 수량과 총 가격까지 관리했고 문제를 해결할 수 있었습니다.&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;조금 더 잘 사용할 수 있게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/70</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-7%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0#entry70comment</comments>
      <pubDate>Mon, 28 Feb 2022 02:04:08 +0900</pubDate>
    </item>
    <item>
      <title>[항해99] 6주차 회고</title>
      <link>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-6%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;한 주에 대한 정리&lt;/b&gt;&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;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;프론트 엔드는 백엔드가 사용하는 용어나 어떻게 서버작업이 되는지 알지 못했고,&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;p data-ke-size=&quot;size16&quot;&gt;서버랑 연결하기 위해서 axios를 사용해 요청하고 응답을 받았는데&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도, 이번 주차를 진행하면서 get, post, put, delete 각 요청에 맞게&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;axios의 형태를 지켜야 오류가 안난다는 것과 토큰의 사용법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드와 같이 작업을 할 때, 어떻게 진행해야 하는지&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;&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;마지막 복습시간으로 지금까지 배운 것을 잘 정리할 수 있으면 좋을 것같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/69</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-6%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0#entry69comment</comments>
      <pubDate>Sun, 20 Feb 2022 20:01:42 +0900</pubDate>
    </item>
    <item>
      <title>[CS] 계층적인 데이터 구조</title>
      <link>https://oagree0123.tistory.com/entry/CS-%EA%B3%84%EC%B8%B5%EC%A0%81%EC%9D%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B5%AC%EC%A1%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #9d9d9d;&quot;&gt;이 글은 '한 권으로 읽는 컴퓨터 구조와 프로그래밍' 을 정리하여 작성한 글입니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;계층적인 데이터 구조&lt;/b&gt;&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;리스트 길이가 n이라면 최대 n번 노드를 순회해야 한다는 것입니다.&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;이 포인터 수에는 제한이 없기 때문에, 메모리 공간이 허용하는 한 원하는데로 데이터를 조작할 수 있습니다.&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;b&gt;2진 트리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 계층적 데이터 구조로 2진 트리가 있는데,&lt;br /&gt;'2진' 이라는 말은 2진수가 아니라 최대 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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;914&quot; data-origin-height=&quot;523&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3XDGL/btrtmfallAj/KAkS9sK9PcjJGq7kKU4Zdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3XDGL/btrtmfallAj/KAkS9sK9PcjJGq7kKU4Zdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3XDGL/btrtmfallAj/KAkS9sK9PcjJGq7kKU4Zdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3XDGL%2FbtrtmfallAj%2FKAkS9sK9PcjJGq7kKU4Zdk%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;304&quot; height=&quot;174&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;914&quot; data-origin-height=&quot;523&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;빙고 게임에서 불리는 숫자를 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;이 알고리즘은 간접 주소 지정을 활용한다는 면에서 단일 연결 리스트의 삭제와 비슷합니다.&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-filename=&quot;blob&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1195&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/D0tIS/btrtejyQtcC/dhIubrBkGMkosI0qtYPHgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/D0tIS/btrtejyQtcC/dhIubrBkGMkosI0qtYPHgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/D0tIS/btrtejyQtcC/dhIubrBkGMkosI0qtYPHgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FD0tIS%2FbtrtejyQtcC%2FdhIubrBkGMkosI0qtYPHgK%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;449&quot; height=&quot;497&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1080&quot; data-origin-height=&quot;1195&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;8, 6, 9, 4, 7을 삽입하는 것으로 알고리즘의 동작을 살펴보겠습니다.&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;gt; 새 노드를 만들고 루트가 이 노드를 가리키게 함 -&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8을 루트에 삽입 -&amp;gt; 루트에 노드가 있음을 확인 -&amp;gt; 루트와 삽입할 숫자 6 비교 -&amp;gt; 6이 작은 것을 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 왼쪽을보고 비어 있으므로 새 노드 삽입 -&amp;gt; 9는 오른쪽 노드에 삽입 -&amp;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-filename=&quot;blob&quot; data-origin-width=&quot;639&quot; data-origin-height=&quot;734&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bCDZS6/btrtlViWGQq/yrVV0EWSDb2h3oaDA8Y9Sk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bCDZS6/btrtlViWGQq/yrVV0EWSDb2h3oaDA8Y9Sk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bCDZS6/btrtlViWGQq/yrVV0EWSDb2h3oaDA8Y9Sk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbCDZS6%2FbtrtlViWGQq%2FyrVV0EWSDb2h3oaDA8Y9Sk%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;277&quot; height=&quot;318&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;639&quot; data-origin-height=&quot;734&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;이 데이터 구조 내부에 숫자가 5개가 있지만, 최대 3번만 비교하면 원하는 숫자를 찾을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, 이 알고리즘에서는 트리를 변경할 필요가 없어 &lt;br /&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-filename=&quot;blob&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;748&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDkUX1/btrtb2472dT/BCnl7khVv5EKR81jzoYko1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDkUX1/btrtb2472dT/BCnl7khVv5EKR81jzoYko1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDkUX1/btrtb2472dT/BCnl7khVv5EKR81jzoYko1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDkUX1%2Fbtrtb2472dT%2FBCnl7khVv5EKR81jzoYko1%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;448&quot; height=&quot;335&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;748&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;트리의 노드 구성은 원소 삽입 순서에 따라 달라지는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 그림은 단일 연결 리스트처럼 보이며,&lt;/p&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;792&quot; data-origin-height=&quot;1042&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SJ31w/btrtei00F56/uukbJDMp8V3p9LStkgZer0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SJ31w/btrtei00F56/uukbJDMp8V3p9LStkgZer0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SJ31w/btrtei00F56/uukbJDMp8V3p9LStkgZer0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSJ31w%2Fbtrtei00F56%2FuukbJDMp8V3p9LStkgZer0%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;280&quot; height=&quot;368&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;792&quot; data-origin-height=&quot;1042&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;따라서, 아래 그림의 오른쪽과 같은 모습의 유지가 필요합니다.&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-filename=&quot;blob&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bv2d6U/btrtgsChpDW/WoXoQ6tyf0aQ9lZjqBNgMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bv2d6U/btrtgsChpDW/WoXoQ6tyf0aQ9lZjqBNgMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bv2d6U/btrtgsChpDW/WoXoQ6tyf0aQ9lZjqBNgMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbv2d6U%2FbtrtgsChpDW%2FWoXoQ6tyf0aQ9lZjqBNgMk%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;409&quot; height=&quot;181&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;340&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;2진 트리에 대상을 검색하는 연산은 트리 깊이에 의해 정의됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, n계층 만큼 아래로 내려가면, n번만 원소 비교를하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;균형 잡힌 트리는 logn번만 비교하면 됩니다.&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;&lt;b&gt;대용량 저장장치&lt;/b&gt;&lt;/h3&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;클러스터는 한 트랙안에 연속적인 섹터로 이루어져, &lt;br /&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;운영체제의 장치 드라이버가 데이터가 연속적으로 저장된 것 같은 착각을 불러일으킵니다.&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;고정된 크기의 블록을 여럿 확보해서 데이터를 이런 블록에 나눠 담아야합니다.&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;장기적으로 데이터를 저장하기 위해서는 디스크를 사용하므로 영구적인 존재가 필요합니다.&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;이제 파일 이름을 디스크에 저장할 방법과 파일의 데이터가 저장된 디스크 블록을 연결할 방법이 필요합니다.&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;b&gt;아이노드&lt;/b&gt;&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;먼저, 블록 중 일부를 아이노드로 따로 지정합니다.&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;그리고 아이노드는 아래 그림처럼 파일 데이터가 들어가 있는 블록에 대한 인덱스도 포함됩니다.&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-filename=&quot;blob&quot; data-origin-width=&quot;975&quot; data-origin-height=&quot;422&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QLjSA/btrtejr2e2Y/vUWadVUOghLqZtHohYgXo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QLjSA/btrtejr2e2Y/vUWadVUOghLqZtHohYgXo1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QLjSA/btrtejr2e2Y/vUWadVUOghLqZtHohYgXo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQLjSA%2Fbtrtejr2e2Y%2FvUWadVUOghLqZtHohYgXo1%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;444&quot; height=&quot;192&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;975&quot; data-origin-height=&quot;422&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;아이노드는 보통 직접 블록 포인터(실제로는 인덱스)가 12개가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 최대 4096 * 12 = 49152바이트 까지 데이터를 저장할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분은 이정도로 충분하지만, 더 커지면 간접블록을 이용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2중 간접은 4GiB&lt;span style=&quot;background-color: #f8f9fa; color: #202122;&quot;&gt;(&lt;/span&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EA%B8%B0%EB%B9%84%EB%B0%94%EC%9D%B4%ED%8A%B8&quot;&gt;기비바이트&lt;/a&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #202122;&quot;&gt;)&lt;/span&gt;, 3중 간접은 4PiB&lt;span style=&quot;background-color: #f8f9fa; color: #202122;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;(&lt;/span&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%ED%8E%98%EB%B9%84%EB%B0%94%EC%9D%B4%ED%8A%B8&quot;&gt;페비바이트&lt;/a&gt;&lt;span style=&quot;background-color: #f8f9fa; color: #202122;&quot;&gt;)&lt;/span&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;디렉터리는 파일 이름과 파일 데이터를 가리키는 아이노드를 연결합니다.&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;그러나 여러 아이노드가 같은 블록을 참조할 수 있습니다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;심볼릭 링크&lt;/b&gt;&lt;/h4&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;252&quot; data-origin-height=&quot;200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y5hJP/btrtoAFafCd/A7DGpiqb3QalxbCoFRz0OK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y5hJP/btrtoAFafCd/A7DGpiqb3QalxbCoFRz0OK/img.png&quot; data-alt=&quot;그래프&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y5hJP/btrtoAFafCd/A7DGpiqb3QalxbCoFRz0OK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy5hJP%2FbtrtoAFafCd%2FA7DGpiqb3QalxbCoFRz0OK%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;252&quot; height=&quot;200&quot; data-origin-width=&quot;252&quot; data-origin-height=&quot;200&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그래프&lt;/figcaption&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;이제는 사용 중인 블록에 대한 정보를 저장할 수 있는 복잡한 구조가 생겼습니다.&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;가용 공간을 추적하는 방법으로 각 블록을 1비트로 표현하는 비트맵 방식이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법은 비트맵이 아주 커질 수 있습니다. 8TB 디스크 드라이브를 다루기 위해 20억 비트가 필요한데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 256MiB의 공간입니다. 물론 전체 디스크의 0.01%보다 적은 공간을 사용하고 모든 비트맵&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;비트맵을 사용하면 간단하고 효율적입니다. 1이 사용중, 0이 사용 가능한 블록을 가리키면&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;예를 들어 디스크 데이터를 기록하는 도중 전원이 꺼질 수 있습니다.&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;조작해 아이노드 번호를 입력함으로 파일을 수리해야 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 시스템 그래프를 뒤지면서 가용 블록 데이터와 비교해주는 fsck 등의 프로그램이 개발되면서&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;fsck는 더 나은 접근 방법이지만, 디스크가 커짐에 따라 시간도 늘어났습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 오류를 더 효율적으로 수정할 수 있도록 설계된 저널링 파일 시스템이 사용됩니다.&lt;/p&gt;</description>
      <category>Computer Science</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/68</guid>
      <comments>https://oagree0123.tistory.com/entry/CS-%EA%B3%84%EC%B8%B5%EC%A0%81%EC%9D%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EA%B5%AC%EC%A1%B0#entry68comment</comments>
      <pubDate>Tue, 15 Feb 2022 02:15:49 +0900</pubDate>
    </item>
    <item>
      <title>[항해99] 5주차 회고</title>
      <link>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-5%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;한 주에 대한 정리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항해의 5주차는 앞서 배운 리액트와 상태 관리를 파이어스토어와 함께&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;어려가지 신경을 써야하는 것들이 많다는 것을 느꼈습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느 컴포넌트에서 서버의 데이터를 받아올 것인지, props를 전달할 것인지 등&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;더 익숙해져야 겠다고 생각했습니다.&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;아래에서는 서버와 통신하기 위해 사용하는 axios를 간단히 알아보겠습니다.&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;b&gt;axios&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #373747;&quot;&gt;Axios는 node.js와 브라우저를 위한&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Promise 기반&lt;span style=&quot;background-color: #ffffff; color: #373747;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;HTTP 클라이언트 입니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;특징&lt;/b&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;span&gt;&amp;nbsp;&lt;/span&gt;XMLHttpRequests&lt;span&gt;&amp;nbsp;&lt;/span&gt;생성&lt;/li&gt;
&lt;li&gt;node.js를 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;http&lt;span&gt;&amp;nbsp;&lt;/span&gt;요청 생성&lt;/li&gt;
&lt;li&gt;Promise&lt;span&gt;&amp;nbsp;&lt;/span&gt;API를 지원&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;size18&quot;&gt;&lt;b&gt;axios 사용법&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;다음은 axios의 간단한 사용법을 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 설치 방법입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1644740411231&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install axios

yarn add axios&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요청을 통해 데이터를 받아오는 방법입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1644740572499&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;axios.get('api/user')
.then((res)=&amp;gt;{
    console.log(res.data);
}).catch((err)=&amp;gt;{
    console.log(err);
})&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;post요청의 형태는 아래와 같습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1644740724994&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;axios.post('api/user', {
    name: 'kim',
    age: '21'
  })
  .then(function (res) {
    console.log(res);
  })
  .catch(function (err) {
    console.log(err);
  });&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;이외에도 put, delete 등의 요청이 있습니다.&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;b&gt;백엔드 없이 요청하기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;실제 API를 가지고 서버 통신을 하고 싶은데 백엔드 개발자가 없을 경우&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;간단하게 테스트하는 방법이 있습니다.&lt;/span&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;mock api 이용하기&lt;/li&gt;
&lt;li&gt;fake 서버 이용하기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 mock api를 만들어 사용했는데, 아래의 github을 이용했습니다.&lt;/p&gt;
&lt;figure id=&quot;og_1644740925501&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;GitHub - typicode/json-server: Get a full fake REST API with zero coding in less than 30 seconds (seriously)&quot; data-og-description=&quot;Get a full fake REST API with zero coding in less than 30 seconds (seriously) - GitHub - typicode/json-server: Get a full fake REST API with zero coding in less than 30 seconds (seriously)&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/typicode/json-server&quot; data-og-url=&quot;https://github.com/typicode/json-server&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/lxjTn/hyNpevpc67/5KDnQKKKYEv0MHdxAVO5mK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/typicode/json-server&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/typicode/json-server&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/lxjTn/hyNpevpc67/5KDnQKKKYEv0MHdxAVO5mK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;GitHub - typicode/json-server: Get a full fake REST API with zero coding in less than 30 seconds (seriously)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Get a full fake REST API with zero coding in less than 30 seconds (seriously) - GitHub - typicode/json-server: Get a full fake REST API with zero coding in less than 30 seconds (seriously)&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.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;&lt;b&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;항해를 점점 진행하면서 어려워지는 것을 느끼고 있고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;배워가는 것도 많아지고 있다는 것을 느끼고 있습니다.&amp;nbsp;&lt;/span&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;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;다음 주는 백엔드와 실제 소통하고 진행하는 것을 기대하고 잘 준비해 보려고 합니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/67</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-5%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0#entry67comment</comments>
      <pubDate>Sun, 13 Feb 2022 17:31:04 +0900</pubDate>
    </item>
    <item>
      <title>[CS] 아날로그 처리 방법</title>
      <link>https://oagree0123.tistory.com/entry/CS-%EC%95%84%EB%82%A0%EB%A1%9C%EA%B7%B8-%EC%B2%98%EB%A6%AC-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #9d9d9d;&quot;&gt;이 글은 '한 권으로 읽는 컴퓨터 구조와 프로그래밍' 을 정리하여 작성한 글입니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;아날로그 처리 방법&lt;/b&gt;&lt;/h3&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;그래서 데이터의 &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;size18&quot;&gt;&lt;b&gt;샘플링&lt;/b&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;샘플링 데이터로부터 아날로그 신호를 다시 만들어야 합니다.&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;무성 영화 시절에도 영화 화면은 1초당 16프레임을 샘플링해 만들었습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;디지털을 아날로그로 변환&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디지털 숫자를 사용해 아날로그 전압을 만들어내기 위해서는 &lt;b&gt;DA 변환기&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;size18&quot;&gt;&lt;b&gt;DA 변환기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 그림은 8비트로 9 수준을 만들어냈습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(0개의 LED를 킨 것 부터 8개를 모두 킨 경우 까지)&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-filename=&quot;blob&quot; data-origin-width=&quot;964&quot; data-origin-height=&quot;702&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kELfc/btrsUDDAumI/td1LKxMCvtHRNdJuU3CJ11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kELfc/btrsUDDAumI/td1LKxMCvtHRNdJuU3CJ11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kELfc/btrsUDDAumI/td1LKxMCvtHRNdJuU3CJ11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkELfc%2FbtrsUDDAumI%2Ftd1LKxMCvtHRNdJuU3CJ11%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;294&quot; height=&quot;214&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;964&quot; data-origin-height=&quot;702&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;아래의 그림은 0 ~ 256 수준의 표현으로 위의 DA 변환기보다 많은 표현을 할 수 있습니다.&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-filename=&quot;blob&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;959&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eqLfQ8/btrsUEWNGNI/ctkMz5m2ASKfPQSEll2DV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eqLfQ8/btrsUEWNGNI/ctkMz5m2ASKfPQSEll2DV0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eqLfQ8/btrsUEWNGNI/ctkMz5m2ASKfPQSEll2DV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeqLfQ8%2FbtrsUEWNGNI%2FctkMz5m2ASKfPQSEll2DV0%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;348&quot; height=&quot;334&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;959&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;이러한 DA 변환기의 모습은 2진수 표현법을 본떴음을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비트 1은 비트 0보다 2배 더 밝고, 비트 2는 비트 0보다 4배더 밝은 빛은 냅니다.&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;위에서는 LED를 사용했지만, &lt;b&gt;실제 변환기(D/A 또는 DAC)&lt;/b&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;size18&quot;&gt;&lt;b&gt;해상도&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해상도는 DAC가 만들어내는 단계 수를 느슨히 표현할 때 쓰입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;느슨히라고 하는 이유는 DAC가 10비트 해상도라면, &lt;br /&gt;실제는 1/2의 10제곱가지씩 수준을 변경할 수 있다는 뜻이기 때문입니다.&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;정확히 말하면, 해상도는 DAC가 만들어낼 수 있는 최대 전압을 단계 수로 나눈 값이어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어, 10비트 DAC가 최대 5V를 만들어 낼 수 있다면, 해상도는 대략 0.005V 입니다&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-filename=&quot;blob&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;379&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwSLk8/btrsSkEyw1w/CSscqTYDfHk5A9x3kDIsK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwSLk8/btrsSkEyw1w/CSscqTYDfHk5A9x3kDIsK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwSLk8/btrsSkEyw1w/CSscqTYDfHk5A9x3kDIsK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwSLk8%2FbtrsSkEyw1w%2FCSscqTYDfHk5A9x3kDIsK1%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;199&quot; height=&quot;131&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;573&quot; data-origin-height=&quot;379&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;DAC를 이용하면 아날로그 파형을 만들 수 있습니다.&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;DAC 입력을 일정한 비율로 변경하면 파형을 만들 수 있는데,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8비트 DAC를 포트 B에 연결하면 아래 그림과 같이 톱니 파형을 만들 수 있습니다.&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-filename=&quot;blob&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;203&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csnNUT/btrs0u6p4if/qrezdJttxekXPfWstdmKJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csnNUT/btrs0u6p4if/qrezdJttxekXPfWstdmKJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csnNUT/btrs0u6p4if/qrezdJttxekXPfWstdmKJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsnNUT%2Fbtrs0u6p4if%2FqrezdJttxekXPfWstdmKJk%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;609&quot; height=&quot;124&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;996&quot; data-origin-height=&quot;203&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;더 복잡한 파형을 만들기 위한 장치에는 데이터를 저장하기 위한 메모리가 들어 있는 경우가 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장치는 추가 회로를 통해 메모리에 있는 데이터를 읽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU가 수행하는 다른 작업과 무관하게 데이터를 일정한 비율로 읽어서 처리하기 위해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 그림처럼 FIFO(First In First Out) 선입선출 설정을 만들어 구현합니다. 이 모습은 큐(Queue)와 같습니다.&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-filename=&quot;blob&quot; data-origin-width=&quot;860&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIn8Yd/btrsY8bzkD5/qouaxkKKOgow8ZeEpZRgDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIn8Yd/btrsY8bzkD5/qouaxkKKOgow8ZeEpZRgDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIn8Yd/btrsY8bzkD5/qouaxkKKOgow8ZeEpZRgDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIn8Yd%2FbtrsY8bzkD5%2FqouaxkKKOgow8ZeEpZRgDk%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;593&quot; height=&quot;175&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;860&quot; data-origin-height=&quot;254&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;FIFO 메모리와 관련한 두가지 트리거 높은 워터터마크, 낮은 워터마크가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;낮은 워터마크는 FIFO가 거의 빈 상태가 될 경우 인터럽트를 발생시키고&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;size14&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #373a3c;&quot;&gt;&lt;b&gt;인터럽트&lt;/b&gt;란&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;CPU&lt;span style=&quot;background-color: #ffffff; color: #373a3c;&quot;&gt;가 특정 기능을 수행하는 도중에 급하게 다른 일을 처리하고자 할 때 사용할 수 있는 기능&lt;/span&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;이러한 방법을 이용하여 고수준의 소프트웨어에서는 일정한 비율로 연속적으로 출력이 일어나도록 메모리를 채울 수 있습니다. 이는 물탱크의 동작과 비슷합니다. 수위가 낮은 워터마크보다 낮으면 펌프를 가동하여 물을 탱크에 넣고, 높은 워터마크에 이르면 펌프를 꺼버립니다. FIFO는 각기 다른 속도로 동작하는 여러 요소를 결합할 때 좋습니다.&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;&lt;b&gt;아날로그를 디지털로 변환&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AD 변환기는(A/D나 ADC) DAC 보다 복잡합니다.&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;아래 그림으로 입력 파형의 샘플을 취해야 합니다.&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-filename=&quot;blob&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;237&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m8i3O/btrsSkxNPM6/WboeojVodb3G7rjnYPDJkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m8i3O/btrsSkxNPM6/WboeojVodb3G7rjnYPDJkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m8i3O/btrsSkxNPM6/WboeojVodb3G7rjnYPDJkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm8i3O%2FbtrsSkxNPM6%2FWboeojVodb3G7rjnYPDJkk%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;392&quot; height=&quot;111&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;237&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;디지털화한 파형이 아날로그 파형과 닮기 위해서는 여러 번 샘플을 얻어야 하는데 &lt;br /&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;/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;b&gt;비교기&lt;/b&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;527&quot; data-origin-height=&quot;328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6BYhw/btrsXs9qAeW/Hs7V5RqGSmmeq5fnxgoPg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6BYhw/btrsXs9qAeW/Hs7V5RqGSmmeq5fnxgoPg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6BYhw/btrsXs9qAeW/Hs7V5RqGSmmeq5fnxgoPg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6BYhw%2FbtrsXs9qAeW%2FHs7V5RqGSmmeq5fnxgoPg0%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;180&quot; height=&quot;112&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;527&quot; data-origin-height=&quot;328&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;비교기의 +입력 신호가 -입력 신호보다 더 크거나 같으면 출력이 1, 그렇지 않으면 0입니다.&lt;/p&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;872&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRXdeA/btrsXagSRUO/OU43ni0s7jNazaYzaK651K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRXdeA/btrsXagSRUO/OU43ni0s7jNazaYzaK651K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRXdeA/btrsXagSRUO/OU43ni0s7jNazaYzaK651K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRXdeA%2FbtrsXagSRUO%2FOU43ni0s7jNazaYzaK651K%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;307&quot; height=&quot;328&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;872&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;플래시 변환기는 번개같이 빠르게 결과를 만들어낸다는 이유로 붙여진 이름이며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 기준에 따라 0.125V보다 낮으면 00000000, 0.250V ~ 0.375V 사이면 00000011 이 되는 식입니다.&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;이 방식도 위에서 본 저수준의 DAC와 똑같이 비트를 효율적으로 쓰지 못하는 문제가 있습니다.&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;br /&gt;이때 기준 전압을 변화시킬 수 있다면, 비교기를 하나만 사용해도 될 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 역할을 DAC 가 해줄 수 있습니다.&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-filename=&quot;blob&quot; data-origin-width=&quot;939&quot; data-origin-height=&quot;626&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VmUJN/btrsXf3f2K5/6vU9TikQ59IyCpNWVcPg20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VmUJN/btrsXf3f2K5/6vU9TikQ59IyCpNWVcPg20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VmUJN/btrsXf3f2K5/6vU9TikQ59IyCpNWVcPg20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVmUJN%2FbtrsXf3f2K5%2F6vU9TikQ59IyCpNWVcPg20%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;413&quot; height=&quot;275&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;939&quot; data-origin-height=&quot;626&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;위의 그림은 저장탱크에서 나온 샘플값을 DAC의 값과 비교기를 사용하여 비교하는 회로입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Clear가 활성화 되면 샘플값이 DAC값과 같을 때까지 카운터 수를 셉니다.&lt;br /&gt;샘플값과 DAC 값이 같아지면 비교기의 출력이 0이 되면서 카운터가 비활성화되므로 원하는 값을 얻습니다.&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;br /&gt;아날로그 신호는 왔다 갔다 하지만, 샘플을 취한 다음 저장 탱크의 출력은 안정적인 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 후 카운터를 0으로 성정하고 DAC 출력과 샘플링된 값이 같을 때까지 수를 셉니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;871&quot; data-origin-height=&quot;376&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HWgPB/btrsXGGh9ZT/VjkoLokz21jo6dLJ8Ibexk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HWgPB/btrsXGGh9ZT/VjkoLokz21jo6dLJ8Ibexk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HWgPB/btrsXGGh9ZT/VjkoLokz21jo6dLJ8Ibexk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHWgPB%2FbtrsXGGh9ZT%2FVjkoLokz21jo6dLJ8Ibexk%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;410&quot; height=&quot;177&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;871&quot; data-origin-height=&quot;376&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DAC 출력이 경사로를 올라가는 것처럼 변하기 때문에 ADC를 램프 변환기라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;램프 변환기는 신호에서 얻은 샘플의 크키게 선형으로 비례하는 시간이 걸리기 때문에 오래 걸린다는 단점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;샘플이 최댓값이고 ADC가 n비트라면 최대 2의n제곱 클록이 걸려야 변환이 끝나게 됩니다.&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;이 변환기는 하드웨어로 2진 검색을 진행합니다.&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-filename=&quot;blob&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MHAKG/btrsYb0EZ3i/NOykzzf7afVStVblvc0l61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MHAKG/btrsYb0EZ3i/NOykzzf7afVStVblvc0l61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MHAKG/btrsYb0EZ3i/NOykzzf7afVStVblvc0l61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMHAKG%2FbtrsYb0EZ3i%2FNOykzzf7afVStVblvc0l61%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;436&quot; height=&quot;247&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;568&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 클록 DAC를 전체 범위의 절반으로 설정합니다. &lt;br /&gt;이 값이 샘플값보다 작으면 DAC 값을 전체 범위의 1/4 만큼 더 증가시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 변경한 값이 샘플값보다 너무 크면 DAC값을 전체 범위의 1/8만큼 더 감소 시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 값이 샘플값보다 더 낮으면 다시 1/6만큼 증가 시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최악의 경우 logn 클록이 걸립니다.&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;DAC에 해상도와 비슷하게 ADC에도 비슷하게 사용합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;554&quot; data-origin-height=&quot;284&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IjBE0/btrsVLaPLUe/d0K1A59adKbIW5HjA5tIxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IjBE0/btrsVLaPLUe/d0K1A59adKbIW5HjA5tIxK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IjBE0/btrsVLaPLUe/d0K1A59adKbIW5HjA5tIxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIjBE0%2FbtrsVLaPLUe%2Fd0K1A59adKbIW5HjA5tIxK%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;269&quot; height=&quot;138&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;554&quot; data-origin-height=&quot;284&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;</description>
      <category>Computer Science</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/66</guid>
      <comments>https://oagree0123.tistory.com/entry/CS-%EC%95%84%EB%82%A0%EB%A1%9C%EA%B7%B8-%EC%B2%98%EB%A6%AC-%EB%B0%A9%EB%B2%95#entry66comment</comments>
      <pubDate>Wed, 9 Feb 2022 02:22:52 +0900</pubDate>
    </item>
    <item>
      <title>[항해99] 4주차 회고</title>
      <link>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-4%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;한 주에 대한 정리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4주차는 React의 숙련 주차였습니다.&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;리액트가 부모 컴포넌트에서 자식 컴포넌트로 props를 전달해 줌에 따라&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;리덕스를 이용했습니다. 또한, firebase를 사용해 서버리스 서비스를 경험해 보았습니다.&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;권장함에 따라 라이프 사이클 메서드를 비교하고 hooks에 대해 간단히 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;라이프 사이클&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 라이프 사이클은 &lt;span style=&quot;background-color: #ffffff; color: #666666;&quot;&gt;컴포넌트가 렌더링을 준비하는 순간부터, 페이지에서 사라질 때까지를 말합니다.&lt;/span&gt;&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;이는 생성될 때(Mount), 업데이트 할 때(Update), 제거할 때(Unmount) 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;클래스 컴포넌트와 함수형 컴포넌트의 사용법이 다른 것을 알아야 합니다.&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;클래스 컴포넌트는 componentDidMount, componentDidUpdate, componentWillUnmount&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;등의 메서드를 사용하고, 함수형 컴포넌트는 useEffect를 활용하여 사용합니다.&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1644148524170&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;[React] 라이프 사이클&quot; data-og-description=&quot;이번에는 리액트 컴포넌트의 라이프 사이클에 대해 알아보겠습니다! 라이프 사이클 컴포넌트가 렌더링을 준비하는 순간부터, 페이지에서 사라질 때까지를 라이프 사이클이라고 합니다. 위의 &quot; data-og-host=&quot;oagree0123.tistory.com&quot; data-og-source-url=&quot;https://oagree0123.tistory.com/60&quot; data-og-url=&quot;https://oagree0123.tistory.com/60&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cA8Wt2/hyNlcquZwA/Z8vEyOYqpyIz7tfMtADBD1/img.png?width=800&amp;amp;height=452&amp;amp;face=0_0_800_452,https://scrap.kakaocdn.net/dn/bIxs6K/hyNlpJ9eKM/qqU7xoRwZVPRTxFoCkDPdK/img.png?width=800&amp;amp;height=452&amp;amp;face=0_0_800_452,https://scrap.kakaocdn.net/dn/cUWuGj/hyNlqoKjMc/4G5yoOqJ4vXi5qffk0Xkf0/img.png?width=1118&amp;amp;height=633&amp;amp;face=0_0_1118_633&quot;&gt;&lt;a href=&quot;https://oagree0123.tistory.com/60&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://oagree0123.tistory.com/60&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cA8Wt2/hyNlcquZwA/Z8vEyOYqpyIz7tfMtADBD1/img.png?width=800&amp;amp;height=452&amp;amp;face=0_0_800_452,https://scrap.kakaocdn.net/dn/bIxs6K/hyNlpJ9eKM/qqU7xoRwZVPRTxFoCkDPdK/img.png?width=800&amp;amp;height=452&amp;amp;face=0_0_800_452,https://scrap.kakaocdn.net/dn/cUWuGj/hyNlqoKjMc/4G5yoOqJ4vXi5qffk0Xkf0/img.png?width=1118&amp;amp;height=633&amp;amp;face=0_0_1118_633');&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;[React] 라이프 사이클&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번에는 리액트 컴포넌트의 라이프 사이클에 대해 알아보겠습니다! 라이프 사이클 컴포넌트가 렌더링을 준비하는 순간부터, 페이지에서 사라질 때까지를 라이프 사이클이라고 합니다. 위의&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;oagree0123.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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;리액트 hooks&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hooks는 위에서 말했듯이 함수형 컴포넌트를 권장함에 따라 생겼습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hooks는 함수형 컴포넌트에서 상태 관리나 라이프 사이클을 사용할 수 있도록 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;useState&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 hooks중 하나인 useState를 보면서 어떻게 사용되고 있는지&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;아래 예제는 useState를 사용하여 더하기 빼기의 역할을 하는 것을 보여줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1644148202930&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React, { useState } from &quot;react&quot;;

const App = () =&amp;gt; {
  const [number, setNumber] = useState(0);
  
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;{number}&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setNumber(number + 1)}&amp;gt;더하기&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setNumber(number - 1)}&amp;gt;빼기&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;const [number, setNumber] = useState(0);&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 useState의 ()안에 값은 초깃값을 setNumber은 상태값의 변경할때 사용됩니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;항해의 4주차는 숙련주차 였던 것 만큼 리액트를 다루는 것에 조금 더 익숙해지고,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;다양한 이론들을 알 수 있었던 시간이었습니다.&lt;/span&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;span style=&quot;color: #303a3e;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;다음주는 주특기 심화주차로 더욱 리액트를 잘 다룰 수 있게 되었으면 좋겠습니다!!&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/64</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-4%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0#entry64comment</comments>
      <pubDate>Sun, 6 Feb 2022 20:58:48 +0900</pubDate>
    </item>
    <item>
      <title>[CS] 메모리 계층과 성능</title>
      <link>https://oagree0123.tistory.com/entry/CS-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B3%84%EC%B8%B5%EA%B3%BC-%EC%84%B1%EB%8A%A5</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #9d9d9d;&quot;&gt;이 글은 '한 권으로 읽는 컴퓨터 구조와 프로그래밍' 을 정리하여 작성한 글입니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;메모리 계층과 성능&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과거에는 CPU와 메모리의 작업 속도가 같았지만,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간이 지남에 따라 CPU는 속도가 빨라졌고, 메모리는 그렇게까지 빨라지지 못해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU 보다 속도가 뒤쳐지기 시작했습니다.&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;이로인해, CPU가 느린 메모리를 기다리느라 아무 일도 하지 않는 경우가 생겼습니다.&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;&lt;b&gt;메모리 계층&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;메모리를 필요에 따라 여러가지 종류로 나누어 둠을 의미합니다&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;이 때 필요한 대부분의 경우&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;CPU&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;가 메모리에 더 빨리 접근하기 위함 입니다.&lt;/span&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;773&quot; data-origin-height=&quot;502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1PYNe/btrsrT7j5Sk/b0DvESolEiTJQ8wIOHew71/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1PYNe/btrsrT7j5Sk/b0DvESolEiTJQ8wIOHew71/img.png&quot; data-alt=&quot;메모리 계층&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1PYNe/btrsrT7j5Sk/b0DvESolEiTJQ8wIOHew71/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1PYNe%2FbtrsrT7j5Sk%2Fb0DvESolEiTJQ8wIOHew71%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;276&quot; height=&quot;179&quot; data-origin-width=&quot;773&quot; data-origin-height=&quot;502&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;메모리 계층&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;레지스터와 캐시는 CPU 내부에 존재합니다. CPU가 아주 빠르게 접근할 수 있습니다.&lt;/li&gt;
&lt;li&gt;주 메모리는 CPU 외부에 존재합니다. 레지스터와 캐시보다 더 느리게 접근 할 수 밖에 없습니다.&lt;/li&gt;
&lt;li&gt;대용량 저장장치는 CPU가 직접 접근할 방법조차 없습니다. CPU가 대용량 저장장치에 접근하기 위해서는 대용량 저장장치의 데이터를 메모리로 이동시키고, 메모리에서 접근해야 합니다. 아주 느린 접근 밖에 불가능합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;컴퓨터-메모리-종류&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;컴퓨터 메모리 종류&lt;/b&gt;&lt;/h3&gt;
&lt;h4 id=&quot;1-레지스터&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;레지스터&lt;/b&gt;&lt;/h4&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;h4 id=&quot;2-캐시&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;캐시&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU 캐시는 메인 메모리에서 가장 자주 사용되는 위치의 데이터를 갖고 있는, 크기는 작지만 빠른 메모리입니다.&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;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;프로세서가 메인 메모리를 읽거나 쓰고자 할 때는, 먼저 그 주소에 해당하는 데이터가 캐시에 존재하는지를 살핍니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;만약 그 주소의 데이터가 캐시에 있으면 데이터를 캐시에서 직접 읽고, 그렇지 않으면 메인 메모리에 직접 접근합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 id=&quot;3-주기억장치메인메모리-1차기억장치&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;주 메모리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU에서 직접 접근이 가능한 메모리. 메모리(memory)는 종종 '기억 장치'라는 용어와 혼용되기도 하지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대체로는 주기억장치를 말하며 특히 램을 가리키는 경우가 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적으로 RAM과 ROM이 존재합니다.&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;b&gt;대용량 저장장치&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;CPU에서 직접 접근이 불가능한 메모리. 접근하려면 디바이스 드라이버와 시스템 콜을 통하여 기억장치의 특정 위치의 내용을 주 메모리 로드(Load)한 뒤 읽어야 합니다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;&lt;/span&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;책에 나온 비유에 따르면, 레지스터는 냉장고와 같이 공간이 많지는 않지만&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;대용량 저장장치는 창고와 같이 공간이 더 많지만 집에서 멀리 떨어져 있습니다.&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;lt; 가게 &amp;lt; 창고 순으로 물건을 많이 가지고 나옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터에서 일어나는 일도 비슷합니다. CPU와 주 메모리 사이에는 작은 덩어리,&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;위에서 CPU와 메모리들 간에 상관 관계에 대해 알아보았습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU가 주 메모리 보다 10배 빠르다고 가정하면, CPU가 메모리를 기다리느라 많은 시간을 소비해야합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 해결하기 위해 식품 저장고와 같은 &lt;b&gt;캐시(cache)&lt;/b&gt;라는 하드웨어를 CPU에 추가합니다.&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;b&gt;캐시의 지역성&lt;/b&gt;&lt;/p&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;책상에서 자주 사용하는 물건을 가까운 자리에 두듯, 자주 사용하는 데이터를 CPU와 가까운 위치에 저장해 필요할 때 마다 빠르게 꺼내쓸 수 있다. 캐시메모리를 사용하면 CPU가 메모리에 접근하는 횟수를 줄여 성능 향상의 효과를 볼 수 있다.&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;&lt;b&gt;주변 접근&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;주 메모리에서 데이터를 가져와 캐시에 어떻게 저장해야 할까요?&lt;/b&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;책 앞의 내용에서, '임의 접근 메모리'(RAM, 151p)를 보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;행을 고정하고 열을 변화시키면서 DRAM을 읽을 때 더 빠르다는 사실을 알 수 있습니다.&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;메모리&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;에서 오고가는 자료를 관리하는 데 쓰이는 &lt;/span&gt;CPU &lt;b&gt;메모리 컨트롤러&lt;/b&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;대부분 연속된 위치의 데이터가 필요하기 때문입니다.(지역성)&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;(주 메모리에서 데이터를 전부 가져오는 대신, 주로 사용하는 데이터를 캐시에 저장합니다.)&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;가 일어나도 CPU는 고속 메모리 접근 모드가 가능하기 때문에 좀더 유리합니다.&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;는 CPU가 캐시에서 어떤 내용(어떤 주 메모리 주소에 들어 있는 내용)을 찾았는데 캐시에 그 데이터가 없어 메모리를 읽어야 하는 경우를 뜻합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;캐시 적중&lt;/b&gt;은 CPU가 원하는 내용을 캐시에서 찾은 경우를 말합니다.&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;캐시 메모리도 계층이 있는데, 모든 캐시가 같은 칩 안에 있어도 CPU와 멀 수록 더 느리고 더 커집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 들을 L1, L2, L3 (L은 level) 캐시라고 부르는데, 이 계층은 음식 저장고와 차고에 여분의 냉장고가 있는 것과 같습니다.&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;심지어 순서를 벗어나는 실행을 처리하는 회로도 존재한다.&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;이 회로는 CPU가 프로그램에 명시된 명령어 순서를 벗어나서 가장 효율적으로 명령어를 수행하게 해줍니다.&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;을 유지하는 것은 아주 어렵습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;캐시 일관성&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;cache coherence&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;)는 &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;공유 메모리 시스템에서 프로세서가 가진 로컬 캐시 간의 일관성을 의미한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d0tTAE/btrsnmP3kgk/0XOkuvPKz6IhdVgiAnlNsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d0tTAE/btrsnmP3kgk/0XOkuvPKz6IhdVgiAnlNsk/img.png&quot; data-alt=&quot;공유 메모리 시스템 개념도&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d0tTAE/btrsnmP3kgk/0XOkuvPKz6IhdVgiAnlNsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd0tTAE%2FbtrsnmP3kgk%2F0XOkuvPKz6IhdVgiAnlNsk%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;400&quot; height=&quot;172&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;172&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;공유 메모리 시스템 개념도&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;각 클라이언트가 자신 만의 로컬&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;캐시&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;를 가지고 다른 여러 클라이언트와 메모리를 공유하고 있을 때, 캐시의 갱신으로 인한 데이터 불일치 문제가 발생한다. 예를 들어 변수 X에 대해서 두 클라이언트가 변수 X를 공유하고 있고 그 값이 0이라고 하자. 이때 클라이언트 1(그림의 윗쪽)이 X에 1을 대입하였고 클라이언트 2(그림의 아래쪽)가 변수 X를 읽어들이게 되면 클라이언트 2는 클라이언트 1에 의해 수정된 값인 1을 받아들이는 것이 아니라 현재 자신의 로컬 캐시에 있는 0을 읽어들이게 된다. 따라서 캐시 1, 2는 같은 X라는 변수에 대해 다른 값을 가지게 되므로 데이터 불일치 문제가 발생한다. 캐시 일관성을 유지한다고 하는 것은 이러한 데이터 불일치 현상을 없애는 것을 의미한다.&lt;/span&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;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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 이 방식은 캐시의 장점을 없애버립니다. 이에 대한 해결 방법은 책의 범위를 벗어납니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코프로세서&lt;/b&gt;&lt;/h3&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;&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;예를 들어 부동소수점 연산을 처리할 회로 공간이 없어서 사용되는 경우가 있었는데, 지금은&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;이런 방식을 직접 메모리 접근(DMA) 이라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 이만큼의 데이터를 저쪽으로 복사하고, 다 끝나면 나한테 알려줘와 같은 방식으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DMA를 설정할 수 있다. CPU는 DMA 장치에 귀찮은 일을 많이 떠맡기기 때문에 유용한 연산을 더 많이&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;&lt;b&gt;정리&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메모리가 CPU보다 속도가 느려, CPU가 느린 메모리를 기다리느라 아무 일도 하지 않는 경우가 생김&lt;/li&gt;
&lt;li&gt;캐시의 사용 이유&lt;br /&gt;데이터는 블록형태로 한번에 넘어온다(지역성)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;반복 접근&lt;/b&gt;&lt;br /&gt;대부분의 메모리 접근은 특정한 위치의 근방에서 자주 일어나는 경향이 있기 때문에, 데이터를 크기는 작지만 속도가 빠른 캐시메모리에 복사해 두면 평균 메모리 접근 시간을 아낄 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;주변 접근&lt;br /&gt;&lt;/b&gt;책상에서 자주 사용하는 물건을 가까운 자리에 두듯, 자주 사용하는 데이터를 CPU와 가까운 위치에 저장해 필요할 때 마다 빠르게 꺼내쓸 수 있다. 캐시메모리를 사용하면 CPU가 메모리에 접근하는 횟수를 줄여 성능 향상의 효과를 볼 수 있다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Computer Science</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/62</guid>
      <comments>https://oagree0123.tistory.com/entry/CS-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B3%84%EC%B8%B5%EA%B3%BC-%EC%84%B1%EB%8A%A5#entry62comment</comments>
      <pubDate>Thu, 3 Feb 2022 15:07:29 +0900</pubDate>
    </item>
    <item>
      <title>[React] 라이프 사이클</title>
      <link>https://oagree0123.tistory.com/entry/REACT-%EB%9D%BC%EC%9D%B4%ED%94%84-%EC%82%AC%EC%9D%B4%ED%81%B4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;이번에는 리액트 컴포넌트의 라이프 사이클에 대해 알아보겠습니다!&lt;/span&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;&lt;b&gt;라이프 사이클&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트가 렌더링을 준비하는 순간부터, 페이지에서 사라질 때까지를 라이프 사이클이라고 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1118&quot; data-origin-height=&quot;633&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnFpKL/btrr1JyGs8a/SikSIpRRGuuCg0nr59B87k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnFpKL/btrr1JyGs8a/SikSIpRRGuuCg0nr59B87k/img.png&quot; data-alt=&quot;[http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/]&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnFpKL/btrr1JyGs8a/SikSIpRRGuuCg0nr59B87k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnFpKL%2Fbtrr1JyGs8a%2FSikSIpRRGuuCg0nr59B87k%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;636&quot; height=&quot;360&quot; data-origin-width=&quot;1118&quot; data-origin-height=&quot;633&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;[http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/]&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 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;&lt;b&gt;라이프 사이클 유형&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라이프 사이클을 크게 3가지 유형으로 나눌 수 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 생성될 때(Mount), 업데이트 할 때(Update), 제거할 때(Unmount) 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Mount&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 마운트(Mount)에 대해서 설명하겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마운트는 DOM이 생성되고 웹 브라우저에 나타나는 것을 의미합니다.&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;Update&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업데이트(Update)는 4가지 상황에 의해 발생합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;props가 변경될 때 (New props)&lt;/li&gt;
&lt;li&gt;state가 변경될 때 (setState())&lt;/li&gt;
&lt;li&gt;부모 컴포넌트가 리렌더링 될 때&lt;/li&gt;
&lt;li&gt;forceUpdate()로 강제렌더링 할 때&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Unmount&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;언마운트(Unmount)는 마운트와 반대로 DOM에서 제거되는 것을 말합니다.&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;&lt;b&gt;라이프 사이클 메서드&lt;/b&gt;&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;constructor&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;constructor는 컴포넌트가 만들어질 때 가장 먼저 실행되는 생성자 메서드 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스형에서 초기 state를 정하기 위해 사용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1643628132831&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// class
class LifeCycle extends React.Component {
  constructor(props) {
    super(props);
  }
}

// Hooks
const LifeCycle = () =&amp;gt; {
  const [item, setItem] = useState('');
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;render&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트를 렌더링하는 메서드로 필수적이고 가장 중요한 메서드 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수형 컴포넌트에선 render을 쓰지 않고 렌더링할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;render 메서드에선 props나 state를 변경하지 않아야 합니다. (state가 바뀌면 다시 Update!)&lt;/p&gt;
&lt;pre id=&quot;code_1643632788444&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// class
class LifeCycle extends React.Component {
  render() {
    return &amp;lt;div&amp;gt;렌더링!&amp;lt;/div&amp;gt;
  }
}

// Hooks
const LifeCycle = () =&amp;gt; {
  return &amp;lt;div&amp;gt;렌더링!&amp;lt;/div&amp;gt;
}&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;b&gt;componentDidMount&lt;/b&gt;&lt;/h4&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;이 메서드는 주로 ajax 요청을 하거나, DOM 속성을 읽고, 직접 변경하는 작업을 수행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1643636087435&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//class
class LifeCycle extends React.Component {
    componentDidMount() {
        // 마운트 로직
    }
}

// Hooks
const LifeCycle = () =&amp;gt; {
    useEffect(() =&amp;gt; {
       // 마운트 로직
    }, []);
}&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;b&gt;componentDidUpdate&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트가 리렌더링이 된 이후에, 화면이 모두 그려지고 호출되는 메서드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메서드는 컴포넌트가 업데이트 되었을 때, DOM을 조작하는데 사용됩니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;// class
class LifeCycle extends Component {
    componentDidUpdate(prevProps, prevState) {
        // 업데이트 로직
    }
}

// Hooks
const LifeCycle = () =&amp;gt; {
    useEffect(() =&amp;gt; {
        // 업데이트 로직
    });
}&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;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;componentWillUnmount&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트가 화면에서 사라지기 직전에 호출되는 메서드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 메서드는 주로 DOM에 직접 연결한 이벤트를 제거하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;setTimeout이 있다면, clearTimeout 메서드로 제거하는 것과 같은 작업을 수행합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1643636419371&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// class
class LifeCycle extends React.Component {
    coomponentWillUnmount() {
        // 언마운트 로직
    }
}

// Hooks
const LifeCycle = () =&amp;gt; {
    useEffect(() =&amp;gt; {
        return () =&amp;gt; {
            // 언마운트 로직
        }
    }, []);
}&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;b&gt;정리&lt;/b&gt;&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;함수형 컴포넌트의 useEffect가 완벽하게 같은 역할을 하는 것은 아니지만 유사하게&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수행하는 것 만큼 꼭 알아두시면 좋을 것 같습니다.!&lt;/p&gt;</description>
      <category>React</category>
      <category>lifecycle</category>
      <category>react</category>
      <category>라이프사이클</category>
      <category>리액트</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/60</guid>
      <comments>https://oagree0123.tistory.com/entry/REACT-%EB%9D%BC%EC%9D%B4%ED%94%84-%EC%82%AC%EC%9D%B4%ED%81%B4#entry60comment</comments>
      <pubDate>Mon, 31 Jan 2022 22:43:14 +0900</pubDate>
    </item>
    <item>
      <title>[React] 리액트란?</title>
      <link>https://oagree0123.tistory.com/entry/React-%EB%A6%AC%EC%95%A1%ED%8A%B8%EB%9E%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;이번에는 자바스크립트 라이브러리 중 하나인 리액트에 대해 알아보겠습니다!&lt;/span&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;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;리액트&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;먼저, 리액트&lt;span style=&quot;background-color: #ffffff;&quot;&gt;(&lt;/span&gt;React&lt;span style=&quot;background-color: #ffffff;&quot;&gt;,&amp;nbsp;&lt;/span&gt;React.js,&lt;span style=&quot;background-color: #ffffff;&quot;&gt; &lt;/span&gt;ReactJS&lt;span style=&quot;background-color: #ffffff;&quot;&gt;)는&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;자바스크립트 라이브러리 중 &lt;span style=&quot;background-color: #ffffff;&quot;&gt;하나로&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&amp;nbsp;&lt;/span&gt;사용자 인터페이스&lt;span style=&quot;background-color: #ffffff;&quot;&gt;를 만들기 위해 사용됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;또한, 리액트는 SPA(Single Page Application)의 UI를 생성하는데 집중한 라이브러리 입니다.&lt;/span&gt;&lt;/span&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;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;리액트의 특징&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;그렇다면 리액트는 왜 사용할까요? 리액트의 특징을 알아보며 생각해봅시다!&lt;/span&gt;&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;1. Component 기반 라이브러리&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;컴포넌트(Component)는 &lt;span style=&quot;background-color: #f8f9fa;&quot;&gt;독립적인 단위의 소프트웨어 모듈을 말합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;리액트는 독립된 컴포넌트들을 조립하여 화면을 보여줍니다.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;리액트는 헤더, 메인 콘텐츠, 네비게이션, 메뉴, 버튼 등 여러 컴포넌트들로 쪼개져 구성할 수 있기 때문에&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;전체적인 코드를 상대적으로 파악하기 쉽고, 기능이나 화면 구성에 따라 묶어 관리할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이러한 독립적인 컴포넌트 구성은 import를 통해 사용할 수 있어 재사용성이 높고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;또한, 오류가 생기면 특정 컴포넌트만 수정하여 사용할 수 있기 때문에 유지보수성을 증가시켜 줍니다.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;2. Virtual DOM&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;먼저, DOM은 HTML, CSS, XML 등을 트리 구조로 인식하고, 데이터를 객체로 간주하여 관리하는 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;DOM은 규모가 큰 웹 애플리케이션에서 직접 접근하여 변화를 주다 보면, 다시 레이아웃을 구성하고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;렌더링하는데 속도가 늦어지게 됩니다.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;리액트에서는 위와 같은 문제점을 가상 돔을 이용해 해결했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;가상 돔은 실제 돔에 접근하여 조작하는 대신, 추상화시킨 자바스크립트 객체를 이용해 사용하는 것입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;데이터가 변할 때, Virtual DOM을 만들어 실제 DOM과 비교하고 전후 상태를 비교합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이후 변경이 필요한 최소한의부분만 실제 DOM에 반영하여 효율성을 높였습니다.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;3. 단방향 데이터 바인딩&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;리액트는 데이터의 흐림이 한 방향으로 흐릅니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;부모 컴포넌트에서 자식 컴포넌트로 한 방향으로 데이터나 내려가며,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;자식 컴포넌트에서 부모 컴포넌트로 데이터를 보낼 수 없습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;부모의 데이트를 바꾸기 위해서는 state를 사용해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;props&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;부모 컴포넌트에서 자식 컴포넌트로 전달해 주는 데이터를 의미합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;props를 전달해준 최상위 부모 컴포넌트만 props를 변경할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;state&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;state는 컴포넌트 내부에서 선언하며 내부에서 값을 변경할 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;state는 사용자와의 상호작용을 통해 데이터를 동적으로 변경할 때 사용합니다.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;4. JSX&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;리액트에서는 JSX라는 자바스크립트의 확장 문법을 사용합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt; JSX는 자바스크립트와 HTML을 동시에 사용할 수 있어 편리하고, &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;자바스크립트 코드를 HTML처럼 표현하기 때문에 가독성이 높습니다.&lt;/span&gt;&lt;/span&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;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이렇게 리액트는 무엇인지? 리액트는 어떤 특징을 가지고 있는지 알아보았습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;이후에는 리액트를 직접 사용하는 방법을 알아보겠습니다!&lt;/span&gt;&lt;/p&gt;</description>
      <category>React</category>
      <category>react</category>
      <category>리액트</category>
      <category>자바스크립트</category>
      <category>프론트엔드</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/59</guid>
      <comments>https://oagree0123.tistory.com/entry/React-%EB%A6%AC%EC%95%A1%ED%8A%B8%EB%9E%80#entry59comment</comments>
      <pubDate>Mon, 31 Jan 2022 16:34:31 +0900</pubDate>
    </item>
    <item>
      <title>[항해99] 3주차 회고</title>
      <link>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-3%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0-1</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;한 주에 대한 정리&lt;/b&gt;&lt;/h4&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;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;리액트에서 리액트 요소가 화면에 그려지고 사라는진데 까지의 사이클&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SPA에서 라우팅 등 어떻게 리액트가 그려지고 작동하는지를 배울 수 있었습니다.&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;아래에서는 라이프 사이클을 이해하기 위해 필요한 DOM과&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;DOM &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 DOM은 Documnet Object Model로 XML이나 HTML 문서에 접근하기 위한 일종의 인터페이스를 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 객체 모델은 문서 내의 모든 요소를 정의하고, 각각 요소에 접근하는 방법을 제공합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;406&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ptbwq/btrr4yproAP/5NRRP1dtmtyGctB9cVC3I1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ptbwq/btrr4yproAP/5NRRP1dtmtyGctB9cVC3I1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ptbwq/btrr4yproAP/5NRRP1dtmtyGctB9cVC3I1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fptbwq%2Fbtrr4yproAP%2F5NRRP1dtmtyGctB9cVC3I1%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;774&quot; height=&quot;406&quot; data-origin-width=&quot;774&quot; data-origin-height=&quot;406&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;DOM의 특징&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 위의 그림은 WC3의 DOM 표준 객체 모델입니다. DOM의 구조는 노드 트리고 표현되며&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;2. 또한, DOM은 HTML 문서로 생성되지만 꼭 일치하는 것은 아닙니다.&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;HTML&lt;span&gt;&amp;nbsp;&lt;/span&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;화면에 보이고자 하는 모양과 구조를 문서로 만든 것으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;단순 텍스트로 구성&lt;br /&gt;(최초에 화면을 그릴때 사용하는 설계도)&lt;/li&gt;
&lt;li&gt;DOM&lt;span&gt;&amp;nbsp;&lt;/span&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;HTML 문서의 내용과 구조가 객체 모델로 변화되어 다양한 프로그램에서 사용됨&lt;br /&gt;(설계도를 이용하여 실제로 화면에 나타내지는 인터페이스)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. DOM은 브라우저에서 보이는 것이 아닙니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저 보이는 것은 렌더 트리로 DOM과 CSSOM의 조합&lt;span style=&quot;color: #555555;&quot;&gt;입니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렌더 트리에는 렌더링 되는 요소만 관련이 있고 스크린에 그려지는 것으로 구성&lt;span style=&quot;color: #555555;&quot;&gt;되어 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;&lt;span&gt;렌더 트리는 &lt;/span&gt;&lt;/span&gt;보이지 않는 요소들은 제외&lt;span style=&quot;color: #555555;&quot;&gt;되기 때문에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;DOM과는 다릅니다. &lt;br /&gt;(DOM은 보이지 않는 요소를 포함하고 렌더 트리는 제외합니다.)&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. DOM은 개발도구에서 보이는 것이 아닙니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;개발도구의 요소 검사기에 보이는 것이 DOM과 가장 비슷한 모습을 보이지만&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt; 개발도구의 요소 검사기는 DOM이 가지고 있지 않은 정보를 가지고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;::befor, ::after의 선택한 가상 요소가 렌더 트리를 구성하는 요소 중 하나이지만,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DOM은 HTML문서로부터 빌드됩니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;서버리스&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버리스는 서버가 없다는 뜻이 아니라 서버를 관리할 필요없이 app을 실행할 수 있도록하는&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;서버리스를 사용하는 이유는 개발자가 클라우드나 온프레미스 서버 또는 런타임 관리와 운영에 대해 시간을 쓰지않고 오로지 핵심 제품에 집중할 수 있기 때문입니다.&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;반복하기 때문에 실행 대기 시간이 오래걸리는 단점이 있습니다.&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;여기까지 DOM과 서버리스에 대해 간단하게 알아보았습니다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;항해의 3주 차는 리액트를 시작하는 기간이었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #303a3e;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;리액트가 어떻게 화면을 그려내는지 컴포넌트가 언제 업데이트 되는지 등&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #303a3e;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;알 수 있었던 시간이었습니다.&lt;/span&gt;&lt;/span&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;span style=&quot;color: #303a3e;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;다음주는 리액트에 대해 더 자세하게 알 수 있을 것 같습니다.!&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/57</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-3%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0-1#entry57comment</comments>
      <pubDate>Sun, 30 Jan 2022 22:12:47 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 함수 표현식 VS 함수 선언식</title>
      <link>https://oagree0123.tistory.com/entry/JAVASCRIPT-%ED%95%A8%EC%88%98-%ED%91%9C%ED%98%84%EC%8B%9D-VS-%ED%95%A8%EC%88%98-%EC%84%A0%EC%96%B8%EC%8B%9D</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;이번에는 자바스크립트에서 함수를 선언하는 방법을 알아보겠습니다! :)&lt;/span&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;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;&lt;b&gt;함수 선언식&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;일반적으로 작성하는 함수 방법입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1643246254987&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function 함수명() {
    //함수 로직
}

function funcDeclarations() {
    return 'function declaration';
}

// 함수 호출
funcDeclarations();&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;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;&lt;b&gt;함수 표현식&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;함수를 변수에 저장하여 활용하는 방식입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1643246350244&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var 함수명 = function () {
    //함수 로직
}

var funcExpression = function () {
    return 'function epression'
}

// 함수 호출
funcExpression();&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;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;&lt;b&gt;함수 선언식 VS &lt;b&gt;함수 표현식&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;&lt;b&gt;&lt;/b&gt;둘의 가장 큰 차이점은 호이스팅에 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;먼저 호이스팅은 선언한 변수나 함수를 코드 상단으로 끌어오리는 것입니다.&lt;/span&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;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;먼저, 예제를 한 번 보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1643247012615&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;funcDeclaration();
funcExpression();

function funcDeclaration() {
    console.log('Declaration!');
}

var funcExpression = function() {
    consolog.log('Expression!');
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;위 코드의 결과가 어떻게 될까요?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;실행결과를 보면 에러가 나는 것을 확인할 수 있습니다.이 결과는 함수 선언식은 호이스팅이 되지만, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; font-family: 'Noto Sans Light';&quot;&gt;함수 표현식은 호이스팅되지 않는 것을 볼 수 있습니다.&lt;/span&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;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;&lt;b&gt;함수 표현식 장점&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;&lt;b&gt;클로저 사용&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;&quot;&gt;먼저, 클릭 이벤트를 추가하는 예제를 보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1643251318616&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function listHandler(index) {
    return function clickEvent(event) {
    	// 클릭할 때 마다 해당 index 값을 표시
        console.log(index); 
    };
}

var lists = document.querySelectorAll('.list');
var i;

for (i = 0; i &amp;lt; lists.length; i += 1) {
    lists[i].onclick = listHandler(i);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 클로저가 사용된 곳은 listHandler()함수의 index를 내부의 clickEvent()함수에서&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;이후 for문이 끝난후 list들을 클릭하면, index값이 클릭한 list의 길이 값과 같은 것을 볼 수 있을 것입니다.&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;pre id=&quot;code_1643251636057&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var lists = document.querySelectorAll('.list');
var i;

for (i = 0; i &amp;lt; lists.length; i += 1) {
    lists[i].onclick = function (e) {
        console.log(i)
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클로저를 사용한 것과 다르게 list의 길이 값만 나올 것입니다.&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;span style=&quot;font-family: 'Noto Sans Light'; color: #333333;&quot;&gt;&lt;b&gt;콜백 함수 사용&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p&gt;&lt;span style=&quot;&quot;&gt;콜백 함수는&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt; 어떤 이벤트가 발생했을 때 호출되거나, &lt;span style=&quot;color: #555555;&quot;&gt;다른 함수의 인자로써 이용되는 함수입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;함수 표현식은 일반적으로 변수에 저장하여 사용하는 형태를 보입니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1643252012643&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var example = function () {
    // 함수 로직
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 콜백 함수로 쓰이면 변수에 저장하지 않고도 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1643252369467&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$(document).ready(function () {
  console.log('ready!'); 
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JavaScript</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/51</guid>
      <comments>https://oagree0123.tistory.com/entry/JAVASCRIPT-%ED%95%A8%EC%88%98-%ED%91%9C%ED%98%84%EC%8B%9D-VS-%ED%95%A8%EC%88%98-%EC%84%A0%EC%96%B8%EC%8B%9D#entry51comment</comments>
      <pubDate>Tue, 25 Jan 2022 20:49:46 +0900</pubDate>
    </item>
    <item>
      <title>[CS] 논리 게이트</title>
      <link>https://oagree0123.tistory.com/entry/CS-%EB%85%BC%EB%A6%AC-%EA%B2%8C%EC%9D%B4%ED%8A%B8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;이 글은 '한 권으로 읽는 컴퓨터 구조와 프로그래밍' 을 정리하여 작성한 글입니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;논리 게이트&lt;/b&gt;&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;복잡한 수도 시스템을 만드는 것처럼 복잡한 회로를 쉽게 만들 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; 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-filename=&quot;logicgate.PNG&quot; data-origin-width=&quot;269&quot; data-origin-height=&quot;545&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9LYwb/btrrD9jsfpg/X3qv4DDLno1kzTYtOzZAf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9LYwb/btrrD9jsfpg/X3qv4DDLno1kzTYtOzZAf0/img.png&quot; data-alt=&quot;논리 게이트 기호표&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9LYwb/btrrD9jsfpg/X3qv4DDLno1kzTYtOzZAf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9LYwb%2FbtrrD9jsfpg%2FX3qv4DDLno1kzTYtOzZAf0%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;269&quot; height=&quot;545&quot; data-filename=&quot;logicgate.PNG&quot; data-origin-width=&quot;269&quot; data-origin-height=&quot;545&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;논리 게이트 기호표&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 data-ke-size=&quot;size16&quot;&gt;이전에 배운 것들과 마찬가지로 AND 게이트 출력은 A와 B가 참인 경우에만 Y에 참이 출력됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;위의 인버터(NOT) 기호에서 동그라미가 없는 기호는 &lt;b&gt;버퍼(buffer)&lt;/b&gt; 라고 하고, 출력을 전달하기만 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면, &lt;span style=&quot;color: #333333;&quot;&gt;인버터 기호는 &lt;span style=&quot;background-color: #ffffff;&quot;&gt;입력에 대한 보수(complement)를 출력합니다. (ex, 0 --&amp;gt; 1&amp;nbsp; /&amp;nbsp; 1 --&amp;gt;&amp;nbsp; 0)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;논리 게이트에서 가장 단순한 회로는 NAND(not and)나 NOR(not or)입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;AND나 OR 게이트 같은 경우에는 NAND나 NOR 회로 출력에 트랜지스터를 붙여 출력을&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;반전시켜야하기 때문에 더 비싸고 반응 속도도 느리고, 전력 소모도 큽니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;따라서 보통 디지털 회로를 설계시 NAND나 NOR 게이트를 주로 사용합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;또한, &lt;span style=&quot;background-color: #ffffff;&quot;&gt;NAND나 NOR 게이트는 표현할 수 있는 논리도 비교적 더 많습니다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;NAND와 NOR 의 두 입력을 같은 입력에 연결하면 인버터를 만들 수 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;(a NAND a나 a NOR a는 NOT a와 같다.)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 76.6413%; height: 113px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.20308%; text-align: center;&quot;&gt;a&lt;/td&gt;
&lt;td style=&quot;width: 32.0522%; text-align: center;&quot;&gt;a NAND a&lt;/td&gt;
&lt;td style=&quot;width: 29.3723%; text-align: center;&quot;&gt;a NOR a&lt;/td&gt;
&lt;td style=&quot;width: 13.5755%; text-align: center;&quot;&gt;NOT a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.20308%; text-align: center;&quot;&gt;T&lt;/td&gt;
&lt;td style=&quot;width: 32.0522%; text-align: center;&quot;&gt;T AND T -&amp;gt; NOT T = F&lt;/td&gt;
&lt;td style=&quot;width: 29.3723%; text-align: center;&quot;&gt;T OR T -&amp;gt; NOT T = F&lt;/td&gt;
&lt;td style=&quot;width: 13.5755%; text-align: center;&quot;&gt;F&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 9.20308%; text-align: center;&quot;&gt;F&lt;/td&gt;
&lt;td style=&quot;width: 32.0522%; text-align: center;&quot;&gt;F AND F -&amp;gt; NOT F = T&lt;/td&gt;
&lt;td style=&quot;width: 29.3723%; text-align: center;&quot;&gt;F OR F -&amp;gt; NOT F = T&lt;/td&gt;
&lt;td style=&quot;width: 13.5755%; text-align: center;&quot;&gt;T&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;아래에는 드모르간 법칙을 이용하여 게이트를 바꿔 그린 것을 볼 수 있습니다.&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;NAND는 OR의 두 입력을 반전시킨 것과 같고, NOR은 AND의 두 입력을 반전시킨 것과 같습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;또한, NAND에 인버터를 연결하면 OR을 그릴 수 있고, 역으로 NAN출력에 NAND로 만든 인버터를 연결하면&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; data-ke-size=&quot;size16&quot;&gt;AND가 됩니다. 이처럼 NAND나 NOR만 이용하면 OR, AND, NOT을 모두 표현하는 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: left;&quot; 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-filename=&quot;드모르간.png&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K4QIA/btrrD8rmu7a/OmhjjDThPRQ3WZOZD4BbU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K4QIA/btrrD8rmu7a/OmhjjDThPRQ3WZOZD4BbU1/img.png&quot; data-alt=&quot;드모르간 법칙을 이용한 NOR, NAND 게이트 다시 그리기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K4QIA/btrrD8rmu7a/OmhjjDThPRQ3WZOZD4BbU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK4QIA%2FbtrrD8rmu7a%2FOmhjjDThPRQ3WZOZD4BbU1%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;550&quot; height=&quot;180&quot; data-filename=&quot;드모르간.png&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;드모르간 법칙을 이용한 NOR, NAND 게이트 다시 그리기&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 data-ke-size=&quot;size16&quot;&gt;위에서는 게이트 작동방법을 알았으니, 이번에는 게이트를 사용할 때 발생할 수 있는 문제를 알아보겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;이력현상을 활용한 잡음 내성 향상&lt;/b&gt;&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;게이트를 연결하는 경우에는 논리 신호가 0에서 1로 순간적으로 바뀌고, 1에서 0으로 순간적으로 바뀐다는&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-filename=&quot;blob&quot; data-origin-width=&quot;1184&quot; data-origin-height=&quot;444&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/on5Hl/btrrDNOc7TG/ZvdvZ2L11Goei6cyosi6J1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/on5Hl/btrrDNOc7TG/ZvdvZ2L11Goei6cyosi6J1/img.png&quot; data-alt=&quot;0에서 1로 변하는 신호 (잡음 글리치)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/on5Hl/btrrDNOc7TG/ZvdvZ2L11Goei6cyosi6J1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fon5Hl%2FbtrrDNOc7TG%2FZvdvZ2L11Goei6cyosi6J1%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;566&quot; height=&quot;212&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1184&quot; data-origin-height=&quot;444&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;0에서 1로 변하는 신호 (잡음 글리치)&lt;/figcaption&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;이로 인해 신호가 문턱값을 여러 번 오락가락해 출력 신호에 글리치(glitch, 작은 오류)가 생깁니다.&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;size18&quot;&gt;&lt;b&gt;이력 현상 (hysteresis)&lt;/b&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;이력 전이 함수는 아래 그림처럼 이전 출력이 0이면 오른쪽 곡선, 출력이 1이면 왼쪽 곡선을 사용합니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;617&quot; data-origin-height=&quot;483&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bP4p3H/btrrDdUj5Br/TcWBUbOt7c0IXlJSR89Te1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bP4p3H/btrrDdUj5Br/TcWBUbOt7c0IXlJSR89Te1/img.png&quot; data-alt=&quot;이력 전이 함수&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bP4p3H/btrrDdUj5Br/TcWBUbOt7c0IXlJSR89Te1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbP4p3H%2FbtrrDdUj5Br%2FTcWBUbOt7c0IXlJSR89Te1%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;225&quot; height=&quot;176&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;617&quot; data-origin-height=&quot;483&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이력 전이 함수&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 data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;슈미트 트리거 (Schimitt trigger)&lt;/b&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;일반적인 게이트보다 복잡하기 때문에 정말 필요한 경우만 사용&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-filename=&quot;blob&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;290&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpwGfp/btrrB4QWVuz/udaBF8mMTFKMsPkS1sQrd0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpwGfp/btrrB4QWVuz/udaBF8mMTFKMsPkS1sQrd0/img.png&quot; data-alt=&quot;슈미트 트리거 게이트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpwGfp/btrrB4QWVuz/udaBF8mMTFKMsPkS1sQrd0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpwGfp%2FbtrrB4QWVuz%2FudaBF8mMTFKMsPkS1sQrd0%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;188&quot; height=&quot;147&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;370&quot; data-origin-height=&quot;290&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;슈미트 트리거 게이트&lt;/figcaption&gt;
&lt;/figure&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;&lt;b&gt;차동 신호&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서로 반대되는 극성을 가진 2개의 신호를 이용한 전송방식 (반전관계)&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;예를 들어보자면 내가 서있는 위치를 0이라고 했을 때, 오른쪽의 친구를 1이라고 설정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유모차가 가까이와 어깨동무하고 있는 친구와 내가 한쪽으로 밀려나지만, 서로의 위치가 바뀌지 않았을 때&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여전히 0과 1을 유지할 수 있습니다. 이처럼 잡음(유모차)가 결괏값에 영향을 주지 못하도록&lt;/p&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;277&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDpc36/btrrPOL2axQ/SkJ3g4CfF9nJ6A8KIv8lC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDpc36/btrrPOL2axQ/SkJ3g4CfF9nJ6A8KIv8lC1/img.png&quot; data-alt=&quot;차동 신호&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDpc36/btrrPOL2axQ/SkJ3g4CfF9nJ6A8KIv8lC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDpc36%2FbtrrPOL2axQ%2FSkJ3g4CfF9nJ6A8KIv8lC1%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;542&quot; height=&quot;150&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;277&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;차동 신호&lt;/figcaption&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;반전관계를 입력받아 단일 신호로 만들어 주는 리시버를 볼 수 있다.&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;넘어가게 될 수 있다. (유모차에 밀려 인도 밖으로 떨어지는 경우)&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;size18&quot;&gt;&lt;b&gt;공통 모드 판별비, CMMR&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Common-Mode Rejection Ratio&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;차동 신호는 전화선 등 다양한 곳에서 사용되고 있습니다.&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;b&gt;연선 케이블링&lt;/b&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;보컬 마이크의 피드백 문제를 해결하기 위해 한 쌍의 마이크를 사용합니다.&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;&lt;b&gt;전파 지연&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;전파 지연은 &lt;span style=&quot;background-color: #ffffff;&quot;&gt;입력신호를 받고서 출력 결과를 나타낼 때까지 걸리는 시간을 의미합니다.&lt;/span&gt;&lt;/span&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;최악의 경우를 가정해서 설계해야 합니다.&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-filename=&quot;blob&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;357&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cy9uqR/btrrJtVFCnD/npB9g9H44bM1TWehq6bYAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cy9uqR/btrrJtVFCnD/npB9g9H44bM1TWehq6bYAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cy9uqR/btrrJtVFCnD/npB9g9H44bM1TWehq6bYAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcy9uqR%2FbtrrJtVFCnD%2FnpB9g9H44bM1TWehq6bYAk%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;485&quot; height=&quot;173&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;357&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;위 그림의 회색 영역은 전파 지연으로 인해 출력을 신뢰할 수 없는 구간 입니다.&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;전파 지연 시간은 처리 기술에 따라 많이 달라집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7400 계열 같은 개별적 부품은 10나노초(1억 분의 1초) 범위에 속합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc;&quot;&gt;어떤 전자 부품의 정격표(데이터시트) 지연 시간은 t&lt;sub&gt;PHL&lt;/sub&gt; t&lt;sub&gt;PLH&lt;/sub&gt; 로 표시합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #fcfcfc;&quot;&gt;PHL은 1에서 0, PLH는 0에서 1로 갈 때 결리는 지연 시간입니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;출력 유형&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;토템폴 출력&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 게이트 출력은 토템폴(totem pole) 이라고 부릅니다.&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;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bn027j/btrrPnOH8dr/BwkkTtA5eSPRcDN4YbEmJ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bn027j/btrrPnOH8dr/BwkkTtA5eSPRcDN4YbEmJ1/img.jpg&quot; data-origin-width=&quot;194&quot; data-origin-height=&quot;259&quot; data-is-animation=&quot;undefined&quot; style=&quot;width: 17.622%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bn027j/btrrPnOH8dr/BwkkTtA5eSPRcDN4YbEmJ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbn027j%2FbtrrPnOH8dr%2FBwkkTtA5eSPRcDN4YbEmJ1%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;194&quot; height=&quot;259&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buMFAZ/btrrJa4oJLw/BHlJf6dqDu1rMldtsDvCT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buMFAZ/btrrJa4oJLw/BHlJf6dqDu1rMldtsDvCT1/img.png&quot; data-origin-width=&quot;990&quot; data-origin-height=&quot;407&quot; data-is-animation=&quot;undefined&quot; data-filename=&quot;blob&quot; width=&quot;426&quot; height=&quot;175&quot; style=&quot;width: 57.2259%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buMFAZ/btrrJa4oJLw/BHlJf6dqDu1rMldtsDvCT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuMFAZ%2FbtrrJa4oJLw%2FBHlJf6dqDu1rMldtsDvCT1%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;990&quot; height=&quot;407&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjd64e/btrrIWrrVfM/uepfnfcMC8NmHyqLJ1j42k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjd64e/btrrIWrrVfM/uepfnfcMC8NmHyqLJ1j42k/img.jpg&quot; data-origin-width=&quot;261&quot; data-origin-height=&quot;269&quot; data-is-animation=&quot;undefined&quot; style=&quot;width: 22.8265%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjd64e/btrrIWrrVfM/uepfnfcMC8NmHyqLJ1j42k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcjd64e%2FbtrrIWrrVfM%2FuepfnfcMC8NmHyqLJ1j42k%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;261&quot; height=&quot;269&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;토템폴과 토템폴 출력&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왼쪽 스키매틱(회로도)의 위쪽 스위치는 출력 1을 얻기 위해 출력과 높은 논릿값 1을 연결하기 때문에 &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;토템폴 출력은 서로 연결할 수 없습니다. 전자 회로에서 입력&amp;nbsp; 0은 음극, 1은 양극에 연결 되기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두 출력을 연결하면 음극과 양극이 직접 연결되는 효과가 나타나 불이나거나 터질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;오픈 컬렉터 출력&lt;/b&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;973&quot; data-origin-height=&quot;334&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/co9YIt/btrrPofMz75/C3834zRBthvk0noLxgUYNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/co9YIt/btrrPofMz75/C3834zRBthvk0noLxgUYNK/img.png&quot; data-alt=&quot;오픈 컬렉터 / 오픈 드레인 출력&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/co9YIt/btrrPofMz75/C3834zRBthvk0noLxgUYNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fco9YIt%2FbtrrPofMz75%2FC3834zRBthvk0noLxgUYNK%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;558&quot; height=&quot;192&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;973&quot; data-origin-height=&quot;334&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;오픈 컬렉터 / 오픈 드레인 출력&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 data-ke-size=&quot;size16&quot;&gt;위 그림을 보면 0 출력은 아무 문제가 없어 보이지만, 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;오픈 컬렉터는 액티브 풀업이 없기 때문에 서로 연결할 수 있으며, 필요하면 출력을 패시브 풀업에 연결할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;패시브 풀업은 풀업 저항을 논리 적인 1값을 공급해주는 공급 전압에 연결한 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;755&quot; data-origin-height=&quot;444&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uWpVY/btrrKwyNUxY/3Jtcc1SpIwijMRBmubE1Kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uWpVY/btrrKwyNUxY/3Jtcc1SpIwijMRBmubE1Kk/img.png&quot; data-alt=&quot;풀업 저항&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uWpVY/btrrKwyNUxY/3Jtcc1SpIwijMRBmubE1Kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuWpVY%2FbtrrKwyNUxY%2F3Jtcc1SpIwijMRBmubE1Kk%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;201&quot; data-origin-width=&quot;755&quot; data-origin-height=&quot;444&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;풀업 저항&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그림에서 5v를 공급해주는 전압과 저항을 연결하고, 오픈 컬렉터를 연결했습니다. 오픈 컬렉터가 열려있을 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5v가 그대로 출력되지만, 닫혀있을 경우 저항이 없는 오픈 컬렉터 쪽만 출력하게 됩니다. 이때 5v의 출력을 1로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오픈 컬렉터의 출력을 0으로 생각하면 위의 문제를 해결할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;와이어드 AND&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오픈 컬렉터 여러 개와 풀업을 사용하면 와이어드 AND를 만들 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDtrpu/btrrOdlluia/JARTkXkiH21CkJUpIBeNYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDtrpu/btrrOdlluia/JARTkXkiH21CkJUpIBeNYK/img.png&quot; data-is-animation=&quot;undefined&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;702&quot; data-filename=&quot;blob&quot; width=&quot;227&quot; height=&quot;195&quot; style=&quot;width: 57.2262%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDtrpu/btrrOdlluia/JARTkXkiH21CkJUpIBeNYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDtrpu%2FbtrrOdlluia%2FJARTkXkiH21CkJUpIBeNYK%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;813&quot; height=&quot;702&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbm3xY/btrrKxxHjQT/crXmghG75tjphDDeS4nlzK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbm3xY/btrrKxxHjQT/crXmghG75tjphDDeS4nlzK/img.jpg&quot; data-origin-width=&quot;256&quot; data-origin-height=&quot;304&quot; data-is-animation=&quot;undefined&quot; style=&quot;width: 41.611%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbm3xY/btrrKxxHjQT/crXmghG75tjphDDeS4nlzK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbbm3xY%2FbtrrKxxHjQT%2FcrXmghG75tjphDDeS4nlzK%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;256&quot; height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;와이어드 AND&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적 원리는 위의 풀업 저항과 같습니다. 그런데 오픈 컬렉터 출력 값 중 출력이 0인 값이 있다면, 전체의 출력도 0이 되고 모두 1을 출력하면 전체 출력도 1이 됩니다. 이와 반대를 와이어드 OR이라고 부르며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;와이어드 AND는 여러 입력이 있는 AND 게이트를 사용하지 않고도 AND 계산이 가능 합니다.&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;&lt;b&gt;트라이스테이트 출력&lt;/b&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;이때 앞의 두 가지 상태만 가진 것이 아닌 꺼진 상태를 포함해 3가지 상태를 가진 트라이스테이트 출력을 사용합니다.&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-filename=&quot;blob&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bROVpV/btrrPPEndbF/jLMrHTkbufMrdkPhxO5Cf1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bROVpV/btrrPPEndbF/jLMrHTkbufMrdkPhxO5Cf1/img.png&quot; data-alt=&quot;트라이스테이트 출력&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bROVpV/btrrPPEndbF/jLMrHTkbufMrdkPhxO5Cf1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbROVpV%2FbtrrPPEndbF%2FjLMrHTkbufMrdkPhxO5Cf1%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;444&quot; height=&quot;159&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;989&quot; data-origin-height=&quot;354&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;트라이스테이트 출력&lt;/figcaption&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;꺼진 상태를 hi-Z라고도 하며, Z는 &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;임피던스 (impedance&lt;/b&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;온저항&lt;span style=&quot;background-color: #ffffff;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;impedance&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;&amp;nbsp;&lt;/span&gt;임피던스&lt;span style=&quot;background-color: #ffffff;&quot;&gt;)는 회로에서&amp;nbsp;&lt;/span&gt;전압&lt;span style=&quot;background-color: #ffffff;&quot;&gt;이 가해졌을 때&amp;nbsp;&lt;/span&gt;전류&lt;span style=&quot;background-color: #ffffff;&quot;&gt;의 흐름을 방해하는 값이다&lt;/span&gt;&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;트라이스테이트 출력을 사용하면 수많은 장치를 직접 연결할 수 있지만, &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;단 하나의 장치만 활성화해야 한다는 단점이 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Computer Science</category>
      <category>Computer Science</category>
      <category>CS</category>
      <category>논리게이트</category>
      <category>이력 현상</category>
      <category>차동신호</category>
      <category>컴퓨터 사이언스</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/50</guid>
      <comments>https://oagree0123.tistory.com/entry/CS-%EB%85%BC%EB%A6%AC-%EA%B2%8C%EC%9D%B4%ED%8A%B8#entry50comment</comments>
      <pubDate>Tue, 25 Jan 2022 19:10:13 +0900</pubDate>
    </item>
    <item>
      <title>[항해99] 2주차 회고</title>
      <link>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-2%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;한 주에 대한 정리&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;항해 2주차는 자바스크립에 대한 구현력을 기르는 시간이었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;알고리즘 문제들을 풀어보면서 자바스크립트의 내장 메서드들을 자유롭게 사용하고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;다양한 유형의 문제들을 풀면서 조금이나마 연습을 할 수 있었습니다.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;이번 주는 알고리즘 주차가 끝나고 리액트에 대한 강의와 숙제가 시작되는 주차이기도 합니다.&lt;/span&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;span style=&quot;color: #333333;&quot;&gt;아래에서는 자바스크립트를 하면 알아야하는 ECMAscript에 대해 조금 설명하겠습니다.&lt;/span&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;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;ES 는 무엇인가&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;ES 는 ECMAScript 의 약자입니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;ECMAScript 는 Ecma 인터내셔널의 ECMA-262 기술 규격에 정의된 표준화된 스크립트 프로그래밍 언어입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;자바스크립트가 개발된 이후 성공하게 되자 MS는J스크립트라는 스크립트 언어를 만들게 됩니다. 자바스크립트와 J스크립트 사이 기능이 같음에도 불구하고 다른점이 많아 이를 표준화하기 위해서 만들어졌습니다.&amp;nbsp;&lt;/span&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;size18&quot;&gt;&lt;b&gt;ES5와 ES6&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;위에서 ES에 대해 설명했습니다. 그렇다면 ES5와 ES6는 무엇일까요?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼전 ES뒤에 숫자는 버전을 의미합니다. 근데 왜 ES5, ES6에 대해서 가장 강조할 까요?&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;ES6에서 바뀐 것&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;this&lt;/li&gt;
&lt;li&gt;변수선언(var, let, const)&lt;/li&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;ES6로 넘어오면서 ES5에서 있었던 단점들을 보완하기 위해 새로운 기능이 생겼고&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;이후에는 ES6에 대해 조금 더 자세하게 작성하겠습니다.&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;b&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;항해의 2주 차는 자바스크립트를 잘하기위해, &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;프로그래밍을 잘하기 위해&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;조금씩 배워나가는 기간이었던 것 같습니다. 아직까지 많은 기간이 남았기 때문에&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;더욱 열심히 의지를 다져가는 기간이라고 생각됩니다.&lt;/span&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;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;이번 주도 이렇게 끝!!!!!!!!!!!!&lt;/span&gt;&lt;/p&gt;</description>
      <category>WIL (Weekly I Learned)</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/47</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-2%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0#entry47comment</comments>
      <pubDate>Sun, 23 Jan 2022 17:46:15 +0900</pubDate>
    </item>
    <item>
      <title>[cs] 텍스트 표현</title>
      <link>https://oagree0123.tistory.com/entry/cs-%ED%85%8D%EC%8A%A4%ED%8A%B8-%ED%91%9C%ED%98%84</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;이 글은 '한 권으로 읽는 컴퓨터 구조와 프로그래밍' 을 정리하여 작성한 글입니다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;텍스트 표현&lt;/b&gt;&lt;/h3&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;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;아스키코드 (ASCII)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(American Standard Code for Information Interchange)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 아이디어 중 1963년부터 가장 많이 쓰이는 코드&lt;/li&gt;
&lt;li&gt;정보 교환을 위한 미국 표준코드&lt;/li&gt;
&lt;li&gt;키보드에 있는 모든 기호에 대해 7비트 수 값을 할당&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;size14&quot;&gt;확장 BCD 교환 코드 (EDCDIC) - 펀치 카드에 사용한 인코딩을 기반으로 만들어진 코드&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&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;431&quot; data-origin-height=&quot;893&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nRReG/btrrb5CsrBQ/IIcDHFoyLnpx0yhF7wGc6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nRReG/btrrb5CsrBQ/IIcDHFoyLnpx0yhF7wGc6k/img.png&quot; data-alt=&quot;[아스키 코드표]&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nRReG/btrrb5CsrBQ/IIcDHFoyLnpx0yhF7wGc6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnRReG%2Fbtrrb5CsrBQ%2FIIcDHFoyLnpx0yhF7wGc6k%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;343&quot; height=&quot;711&quot; data-origin-width=&quot;431&quot; data-origin-height=&quot;893&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;[아스키 코드표]&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아스키코드 표를 보면 'A'라는 글자의 10진 값은 65, 16진 값은 0x41 이라는 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;제어 문자, Control Character&lt;/b&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;br /&gt;(ex, ACK - '메시지를 받았음', NAK - '메시지를 받지 못했음')&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;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;다른 표준의 진화&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;국제 표준화 기구에서(ISO), 유럽 언어에 필요한 엑센트 기호나 발음 구별 기호 추가&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;위와 같이 각기 다른 표준이 생긴 이유는 비트가 지금보다 비싼 시절에 표준이 만들어 졌기 때문에 7비트나 8비트에 욱여 넣기 위해서 입니다. 이후 비트 가격이 떨어짐에 따라 &lt;b&gt;유니코드(Unicode)&lt;/b&gt; 라는 새로운 표준이 등장했고 문자에 16비트 코드를 부여했습니다. 지금은 21비트까지 확장되었습니다.&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;유니코드(Unicode)&lt;/b&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;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;전 세계의 모든 문자를&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;컴퓨터&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;에서 일관되게 표현하고 다룰 수 있도록 설계된 산업&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;표준&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;U+ 라는 접두어가 붙어있으면 유니코드 라는 의미&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;아스키코드의 0x41은 대문자 A이고, 이를 유니코드표에서 찾으면 U+0041&lt;/span&gt;&lt;/span&gt;&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;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;유니코드 변환 형식 8비트 (UTF-8)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&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;UTF-8 방식이 하위 호환성과 효율성 때문에 가장 널리 쓰임&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;b&gt;인코딩(encoding)&lt;/b&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;size18&quot;&gt;&lt;b&gt;UTF-8 인코딩 방법&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;UTF-8은 문자를 8비트 덩어리(옥텟, octet)의 시퀀스로 인코딩&lt;/li&gt;
&lt;li&gt;첫 번째 덩어리의 MSB 쪽에 있는 비트들이 옥텟의 시퀀스 길이를 표현&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;size18&quot;&gt;&lt;b&gt;UTF-8로 변환된&lt;span&gt;&amp;nbsp;&lt;/span&gt;유니코드&lt;span&gt;&amp;nbsp;&lt;/span&gt;문자의 용량&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;1바이트(8비트)를 차지하는 글자는 U+0000~007F 영역으로서, 아스키 코드의 127개의 문자&lt;/li&gt;
&lt;li&gt;2바이트(16비트)를 차지하는 글자는 U+0080~07FF 영역으로서, 유니코드/0000~0FFF의 일부인 제어문자, 라틴어, 음성기호, 조정문자, 결합문자, 그리스어, 키릴(러시아어 등), 아르메니아어, 히브리어, 아랍어, 시리아어, 타나문자(몰디브), 은코문자(아프리카)의 1920개의 문자&lt;/li&gt;
&lt;li&gt;3바이트(24비트)를 차지하는 글자는 U+0800~FFFF 영역으로서, 유니코드/0000~0FFF의 일부부터(사마리아 문자~) 유니코드/F000~FFFF까지라는 유니코드 대부분의 문자들 6만여개가 포함(한글은 3바이트 구간)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;UTF8METHOD.png&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blIBk9/btrrcO8QHID/9cv464JLTG0NpK8seM3XXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blIBk9/btrrcO8QHID/9cv464JLTG0NpK8seM3XXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blIBk9/btrrcO8QHID/9cv464JLTG0NpK8seM3XXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblIBk9%2FbtrrcO8QHID%2F9cv464JLTG0NpK8seM3XXK%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;647&quot; height=&quot;408&quot; data-filename=&quot;UTF8METHOD.png&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;630&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;UTF-8은 가변바이트를 사용하기 때문에, 1바이트로 표현이 충분한 A같은 경우는 0x41로 표현&lt;/li&gt;
&lt;li&gt;다음 &amp;pi; 기호의 유니코드는 2개의 옥텟을 사용하되, 첫 번째 덩어리의 MSB 3비트를 110으로 시작하고&lt;br /&gt;두 번재 덩어리의 MSB 2비트는 10으로 시작&lt;/li&gt;
&lt;li&gt;한글 '한'은 3개의 옥텟을 사용하여 표현&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>Computer Science</category>
      <category>UTF-8</category>
      <category>아스키코드</category>
      <category>유니코드</category>
      <category>텍스트표현</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/45</guid>
      <comments>https://oagree0123.tistory.com/entry/cs-%ED%85%8D%EC%8A%A4%ED%8A%B8-%ED%91%9C%ED%98%84#entry45comment</comments>
      <pubDate>Thu, 20 Jan 2022 23:11:54 +0900</pubDate>
    </item>
    <item>
      <title>[항해99] 1주차 회고</title>
      <link>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-1%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;한 주에 대한 정리&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항해99 부트캠프를 시작하고 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;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;항해의 1주 차는 팀으로 미니 프로젝트를 수행하고 완성하며 이후 긴 시간을 적응하기 위한 준비의 기간이었습니다. 저희 조는 4명으로(중간에 한 분이 하차하셨지만..) 스타벅스 음료들을 리뷰하는 웹 사이트를 만들었습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: justify;&quot; 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;다음에는 프로젝트를 진행하면서 알게 된 것에 대해 정리해 보겠습니다.&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;b&gt;API&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API는 Application Programming Interface의 약자로 응용 프로그램에서 사용할 수 있도록, 운영체제나 프로그래밍 언어가 제공하는 기능을 제어할 수 있게 만드는 인터페이스를 의미합니다.&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;웹에서 API는 개발에서 다른 서비스에 요청을 보내고 응답을 받기 위해 정의된 명세라고 설명할 수 있습니다. 오픈 API를 이용하면 구글 지도, 네이버 지도, 우편번호 등 다양한 서비스를 쉽게 사용할 수 있습니다.&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;프로젝트를 진행하면서 저희 조도 로그인, 포스트 작성, 리뷰 조회 등 데이터베이스에 정보들을 저장하고, 정보들을 받아오는 역할을 하는 다양한 API에 대해 설계를 해보았습니다. 프로젝트가 크지 않은 만큼 작은 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;b&gt;&lt;b&gt;JWT&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT는 JSON Web Token의 약자로 JSON 구조를 이용하여 사용자에 대한 속성을 저장하는 Claim 기반의 웹 토큰입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 풀어서 설명하자면 인증에 필요한 정보들을 암호화하여 사용하는 토큰입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JWT의 장점은 토큰을 발급한 후 암호화된 것을 검증만 하면 되기 때문 별도의 인증 저장소가 필요하지 않다는 것입니다.&amp;nbsp; 단점은 &lt;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;JWT는 토큰의 길이가 길어, 인증 요청이 많아질수록 네트워크 부하가 심해질 수 있으며, payload에 저장되는 유저의 정보 자체는 암호화되지 않기 때문에 중요한 정보는 담을 수 없습니다.&lt;/span&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;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;우리 조의 프로젝트에서도 로그인을 JWT 방식을 사용했는데, 이전에 쿠키/세션 방식을 이용해 보았다면 비교해 보았을 텐데 직접 사용해 본 적이 없어 아직까지 몸으로 느끼는 장단점은 없었습니다.&amp;nbsp;&lt;/span&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;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;이후에 RESTful API와 JWT, 토큰/세션 등에 대해서는 더 자세히 작성하려고 합니다.&lt;/span&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;b&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;이번 항해의 1주 차를 정리해 보자면, 걱정했던 만큼 어려움이 있었던 것은 아니었습니다. 하루 종일 컴퓨터 앞에 앉아있어야 한다는 생각과 '내가 프로젝트 등을 진행할 수 있을까'라는 걱정이 컸었는데 너무 쉽지도 않게 너무 어렵지도 않게 진행한 것 같습니다. 이후에는 어떻게 될지 모르겠지만 목표를 가지고 시작한 만큼 최선을 다하려고 합니다!&lt;/span&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;span style=&quot;background-color: #ffffff; color: #303a3e;&quot;&gt;이번 주는 이렇게 끝!!!!&lt;/span&gt;&lt;/p&gt;</description>
      <category>WIL (Weekly I Learned)</category>
      <category>API</category>
      <category>JWT</category>
      <category>web</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/33</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%95%AD%ED%95%B499-1%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0#entry33comment</comments>
      <pubDate>Sun, 16 Jan 2022 21:59:10 +0900</pubDate>
    </item>
    <item>
      <title>깊이 우선 탐색 (DFS)과 너비 우선 탐색 (BFS)</title>
      <link>https://oagree0123.tistory.com/entry/%EA%B9%8A%EC%9D%B4-%EC%9A%B0%EC%84%A0-%ED%83%90%EC%83%89-DFS%EA%B3%BC-%EB%84%88%EB%B9%84-%EC%9A%B0%EC%84%A0-%ED%83%90%EC%83%89-BFS</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7534213975012335&quot; data-ad-slot=&quot;1383201687&quot;&gt;&lt;/ins&gt;깊이 우선 탐색 (Depth First Search)&lt;/b&gt;&lt;/h3&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;500&quot; width=&quot;270&quot; height=&quot;270&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIhLsv/btrfgYBJ3MN/c9naE9AZX4jVI72ke0ek91/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIhLsv/btrfgYBJ3MN/c9naE9AZX4jVI72ke0ek91/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIhLsv/btrfgYBJ3MN/c9naE9AZX4jVI72ke0ek91/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/cIhLsv/btrfgYBJ3MN/c9naE9AZX4jVI72ke0ek91/img.gif&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;500&quot; width=&quot;270&quot; height=&quot;270&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&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;/li&gt;
&lt;li&gt;주로 스택을 사용하여 구현합니다.&lt;/li&gt;
&lt;/ol&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;자바스크립트 코드&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 dfs 탐색입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-origin-width=&quot;233&quot; data-origin-height=&quot;226&quot; data-filename=&quot;캡처.PNG&quot; width=&quot;155&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ni2h4/btrfiybO6ci/krd2loScWHR5bRL93sEhpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ni2h4/btrfiybO6ci/krd2loScWHR5bRL93sEhpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ni2h4/btrfiybO6ci/krd2loScWHR5bRL93sEhpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNi2h4%2FbtrfiybO6ci%2Fkrd2loScWHR5bRL93sEhpK%2Fimg.png&quot; data-origin-width=&quot;233&quot; data-origin-height=&quot;226&quot; data-filename=&quot;캡처.PNG&quot; width=&quot;155&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1631856904861&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const graph = {
  '1': ['2', '5', '9'],
  '2': ['1', '3'],
  '3': ['2', '4'],
  '4': ['3'],
  '5': ['1', '6', '8'],
  '6': ['5', '7'],
  '7': ['6'],
  '8': ['5'],
  '9': ['1', '10'],
  '10': ['9'],
};

let unvisited =[];
let visited = [];

function dfs(graph, start){
  unvisited.push(start);
  
  while(unvisited.length !== 0){
    const node = unvisited.pop();
    
    if(!visited.includes(node)){
      visited.push(node);
      unvisited = [...unvisited, ...graph[node]];
    }
  }
  
  return visited;
}

console.log(dfs(graph, &quot;1&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;너비 우선 탐색 (Breadth First Search)&lt;/b&gt;&lt;/h3&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;500&quot; width=&quot;269&quot; height=&quot;269&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CQiK7/btrfgZHpASg/74NhySa95rorMMW93MacKk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CQiK7/btrfgZHpASg/74NhySa95rorMMW93MacKk/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CQiK7/btrfgZHpASg/74NhySa95rorMMW93MacKk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/CQiK7/btrfgZHpASg/74NhySa95rorMMW93MacKk/img.gif&quot; data-origin-width=&quot;500&quot; data-origin-height=&quot;500&quot; width=&quot;269&quot; height=&quot;269&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&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;/li&gt;
&lt;li&gt;주로 큐를 사용하여 구현합니다.&lt;/li&gt;
&lt;/ol&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;자바스크립트 코드&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 bfs 탐색입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; width=&quot;155&quot; data-origin-width=&quot;233&quot; data-origin-height=&quot;226&quot; data-filename=&quot;캡처.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ni2h4/btrfiybO6ci/krd2loScWHR5bRL93sEhpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ni2h4/btrfiybO6ci/krd2loScWHR5bRL93sEhpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ni2h4/btrfiybO6ci/krd2loScWHR5bRL93sEhpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNi2h4%2FbtrfiybO6ci%2Fkrd2loScWHR5bRL93sEhpK%2Fimg.png&quot; width=&quot;155&quot; data-origin-width=&quot;233&quot; data-origin-height=&quot;226&quot; data-filename=&quot;캡처.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1631857922812&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const graph = {
  '1': ['2', '5', '9'],
  '2': ['1', '3'],
  '3': ['2', '4'],
  '4': ['3'],
  '5': ['1', '6', '8'],
  '6': ['5', '7'],
  '7': ['6'],
  '8': ['5'],
  '9': ['1', '10'],
  '10': ['9'],
};

let unvisited =[];
let visited = [];

function bfs(graph, start){
  unvisited.push(start);
  
  while(unvisited.length !== 0){
    const node = unvisited.shift();
    if(!visited.includes(node)){
      visited.push(node);
      unvisited = [...unvisited, ...graph[node]];
    }
  }
  
  return visited;
}

console.log(bfs(graph, &quot;1&quot;));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <category>Algorithm</category>
      <category>BFS</category>
      <category>DFS</category>
      <category>깊이우선탐색</category>
      <category>너비우선탐색</category>
      <category>알고리즘</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/26</guid>
      <comments>https://oagree0123.tistory.com/entry/%EA%B9%8A%EC%9D%B4-%EC%9A%B0%EC%84%A0-%ED%83%90%EC%83%89-DFS%EA%B3%BC-%EB%84%88%EB%B9%84-%EC%9A%B0%EC%84%A0-%ED%83%90%EC%83%89-BFS#entry26comment</comments>
      <pubDate>Fri, 17 Sep 2021 15:08:52 +0900</pubDate>
    </item>
    <item>
      <title>이진 탐색 (Binary Search)</title>
      <link>https://oagree0123.tistory.com/entry/%EC%9D%B4%EC%A7%84-%ED%83%90%EC%83%89-Binary-Search</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;이진 탐색&lt;/b&gt;&lt;/h3&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;start, end로 mid 값을 설정합니다.&lt;/li&gt;
&lt;li&gt;mid 값과 찾고자 하는 값과 비교합니다.&lt;/li&gt;
&lt;li&gt;찾고자 하는 값이 mid 보다 높으면 start = mid + 1, &lt;br /&gt;찾고자 하는 값이 mid 보다 낮으면 end = mid - 1&lt;/li&gt;
&lt;li&gt;값을 찾거나 start 위치가 end를 넘어설때까지 반복합니다.&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;11을 찾는 아주아주 간단한 예를 보겠습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 44.7674%; height: 31px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;5&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;7&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;9&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;11&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;13&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; start&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; mid&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; end&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 11 &amp;gt; mid&amp;nbsp; 이므로, start의 위치를 9로 옮김&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 44.7674%; height: 31px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;1&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;3&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;5&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;7&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;9&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;11&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;13&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;start&amp;nbsp; &amp;nbsp; mid&amp;nbsp; &amp;nbsp; &amp;nbsp;end&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 11 = mid 이므로, 종료&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;&lt;b&gt;자바스크립트 코드&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1631846593214&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function binarySearch(arr, target){
  let startIdx = 0;
  let endIdx = arr.length - 1;
  
  while(startIdx &amp;lt;= endIdx){
    let midIdx = Math.floor((startIdx + endIdx) / 2);
    
    if(arr[midIdx] === target){
      return midIdx;
    }
    else if(arr[midIdx] &amp;lt; target){
      startIdex = midIdx + 1;
    }
    else if(arr[midIdx] &amp;gt; target){
      endIdx = midIdx - 1;
    }
  }
  
  return -1;
}

let nums = [10, 20, 30, 40, 50, 60]; 
console.log(binarySearch(nums, 30));&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;이진 탐색 알고리즘은 mid와 비교해서 절반씩 범위를 줄여나가며 데이터를 찾는 알고리즘입니다. 내용에서 특별히 어려운 부분은 없으니 공부하시면 좋을 것 같습니다. : &amp;gt;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <category>algoritm</category>
      <category>binary search</category>
      <category>알고리즘</category>
      <category>이진 탐색</category>
      <category>프론트엔드</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/25</guid>
      <comments>https://oagree0123.tistory.com/entry/%EC%9D%B4%EC%A7%84-%ED%83%90%EC%83%89-Binary-Search#entry25comment</comments>
      <pubDate>Fri, 17 Sep 2021 11:45:14 +0900</pubDate>
    </item>
    <item>
      <title>힙 정렬 (Heap Sort)</title>
      <link>https://oagree0123.tistory.com/entry/%ED%9E%99-%EC%A0%95%EB%A0%AC-Heap-Sort</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;
&lt;script&gt; MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} }; &lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;힙 정렬&lt;/b&gt;&lt;/h3&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;&lt;b&gt;힙 (Heap)&lt;/b&gt;&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;힙 정렬을 다시 말하자면, 최소 힙이나 최대 힙을 이용하여 정렬하는 방법입니다. 내림차순 정렬을 위해서는 최대 힙을 사용하고, 오름차순 정렬을 위해서는 최소 힙을 사용합니다.&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;정렬할 데이터들을 최대 힙으로 만듭니다.&lt;/li&gt;
&lt;li&gt;최대 힙의 루트에 있는 가장 큰 값을 마지막 요소와 교환하여, 힙의 사이즈를 줄입니다.&lt;/li&gt;
&lt;li&gt;최대 힙을 다시 구성합니다.&lt;/li&gt;
&lt;li&gt;힙의 사이즈가 1보다 크면 위의 과정을 반복합니다.&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;1) 최댓값인 루트의 9를 삭제 후, 마지막 노드를 가져옵니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;807&quot; data-origin-height=&quot;250&quot; data-filename=&quot;캡처.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/duleYq/btrfarvbGWn/JaoJ3ImppKswdY1rXWwbXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/duleYq/btrfarvbGWn/JaoJ3ImppKswdY1rXWwbXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/duleYq/btrfarvbGWn/JaoJ3ImppKswdY1rXWwbXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FduleYq%2FbtrfarvbGWn%2FJaoJ3ImppKswdY1rXWwbXK%2Fimg.png&quot; data-origin-width=&quot;807&quot; data-origin-height=&quot;250&quot; data-filename=&quot;캡처.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&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;2) 루트로 삽입된 노드와 자식 노드와 비교하여 큰 값과 교환합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;257&quot; data-filename=&quot;캡처.PNG&quot; width=&quot;515&quot; height=&quot;245&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7ExKG/btre9FUDjH0/zK8c2jlpTqfkS8OirWNSrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7ExKG/btre9FUDjH0/zK8c2jlpTqfkS8OirWNSrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7ExKG/btre9FUDjH0/zK8c2jlpTqfkS8OirWNSrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7ExKG%2Fbtre9FUDjH0%2FzK8c2jlpTqfkS8OirWNSrk%2Fimg.png&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;257&quot; data-filename=&quot;캡처.PNG&quot; width=&quot;515&quot; height=&quot;245&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&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;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;&lt;b&gt;시간 복잡도&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;완전 이진 트리인 힙의 높이는 $O(logn)$입니다. 데이터 하나를 힙에 삽입, 삭제하는 과정에서 힙을 재구성하는 시간은 $O(logn)$가 소요됩니다. 이에 요소개수 n개를 곱하면 전체 $O(nlogn)$의 시간 복잡도를 가집니다.&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;&lt;b&gt;자바스크립트 코드&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1631673513451&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let arrLen;

function swap(arr, i, j){
  let temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}

function heapify(arr, i){
  let max = i;
  let left = 2 * i + 1;
  let right = 2 * i + 2;
  
  if(left &amp;lt; arrLen &amp;amp;&amp;amp; arr[left] &amp;gt; arr[max]){
    max = left;
  }
  
  if(right &amp;lt; arrLen &amp;amp;&amp;amp; arr[right] &amp;gt; arr[max]){
    max = right;
  }
  
  if(max != i){
    swap(arr, i, max);
    heapify(arr, max);
  }
}

function heapSort(arr){
  arrLen = arr.length;

  for(let i = Math.floor(arrLen / 2); i &amp;gt;= 0; i--){
    heapify(arr, i);
  }
  
  for(let i = arrLen - 1; i &amp;gt; 0; i--){
    swap(arr, 0, i);
    arrLen--;
    
    heapify(arr, 0);
  }
  
  return arr;
}

console.log(heapSort([13, 1, 3, 7, 9, 11, 5]));&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;b&gt;장점&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도가 $O(nlogn)$으로 빠른 편에 속합니다.&lt;/li&gt;
&lt;li&gt;가장 큰 값을 구하거나 가장 작은 값을 구할 때 좋습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 프로그램에 구현할 경우 평균 계산 속도가 퀵 정렬보다 느리고 불안정합니다.&lt;/span&gt;&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;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정리&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힙 정렬은 이름에도 힙이 드러가는 만큼 자료구조 힙을 사용하여 정렬을 수행합니다. 이는 힙에 대한 지식이 없으면 이해하기 힘드니 공부하고 오시는 것을 추천드립니다. 만약 힙에 대해 알고있다면, 어려운 내용은 아닐 것입니다. : &amp;gt;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <category>Algorithm</category>
      <category>Heap Sort</category>
      <category>알고리즘</category>
      <category>자바스크립트</category>
      <category>힙정렬</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/24</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%9E%99-%EC%A0%95%EB%A0%AC-Heap-Sort#entry24comment</comments>
      <pubDate>Wed, 15 Sep 2021 11:56:54 +0900</pubDate>
    </item>
    <item>
      <title>퀵 정렬 (Quick Sort)</title>
      <link>https://oagree0123.tistory.com/entry/%ED%80%B5-%EC%A0%95%EB%A0%AC-Quick-Sort</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;
&lt;script&gt; MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} }; &lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;퀵 정렬&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퀵 정렬은 1) 분할 정복 알고리즘의 하나로, 평균적으로 매우 빠른 수행 속도를 자랑합니다.&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;size18&quot;&gt;&lt;b&gt;1) 분할 정복&lt;/b&gt;&lt;/p&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;159&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzWZ3s/btreKIzp6nJ/yEIJr6JbLl8BIftlSZkVi1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzWZ3s/btreKIzp6nJ/yEIJr6JbLl8BIftlSZkVi1/img.gif&quot; data-alt=&quot;https://visualgo.net/en/sorting&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzWZ3s/btreKIzp6nJ/yEIJr6JbLl8BIftlSZkVi1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bzWZ3s/btreKIzp6nJ/yEIJr6JbLl8BIftlSZkVi1/img.gif&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;159&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://visualgo.net/en/sorting&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 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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;데이터들의 배열에서 하나의 원소를 선택합니다. 선택된 원소를 피벗(pivot)이라고 부릅니다.&lt;/li&gt;
&lt;li&gt;피벗을 기준으로 왼쪽에는 피벗보다 작은 값, 오른쪽에는 피벗보다 높은 값이 오도록 배열을 분할합니다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;피벗을 제외한 왼쪽 배열과 오른쪽 배열을 다시 정렬합니다.&lt;/li&gt;
&lt;li&gt;더이상 분할이 불가능할 때까지 반복합니다.&amp;nbsp;&lt;/li&gt;
&lt;/ol&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;&lt;b&gt;시간 복잡도&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 최악의 경우&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퀵 정렬의 최악의 경우는 오름차순이나 내림차순으로 이미 정렬이 되어있는 경우입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;447&quot; data-filename=&quot;캡처.PNG&quot; width=&quot;422&quot; height=&quot;408&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnuzY5/btreKKD4ZgN/oHQAMoeDxmYusBHwdEeui0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnuzY5/btreKKD4ZgN/oHQAMoeDxmYusBHwdEeui0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnuzY5/btreKKD4ZgN/oHQAMoeDxmYusBHwdEeui0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnuzY5%2FbtreKKD4ZgN%2FoHQAMoeDxmYusBHwdEeui0%2Fimg.png&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;447&quot; data-filename=&quot;캡처.PNG&quot; width=&quot;422&quot; height=&quot;408&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 오름차순으로 정렬되어 있을 때, 가장 왼쪽의 원소를 피벗으로 잡는 경우를 살펴보겠습니다. 이 경우에는 위의 그림과 같이 오른쪽에 분열된 배열만 생성될 것입니다. 이를 피벗을 설정하는 n번의 과정과, 재귀호출마다 n번의 비교 연산으로, 피벗을 설정하는 횟수 * 비교 연산 = $O(n^2)$의 시간 복잡도를 가지게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 최선의 경우&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퀵 정렬의 최선의 경우에는 피벗이 중앙에 위치하여 원소들을 절반으로 분할 하였을 경우입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;341&quot; data-filename=&quot;캡처.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qb0Oq/btreMDKWqg9/0ZIlCHH0LUnLnlEXkRDTrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qb0Oq/btreMDKWqg9/0ZIlCHH0LUnLnlEXkRDTrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qb0Oq/btreMDKWqg9/0ZIlCHH0LUnLnlEXkRDTrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqb0Oq%2FbtreMDKWqg9%2F0ZIlCHH0LUnLnlEXkRDTrk%2Fimg.png&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;341&quot; data-filename=&quot;캡처.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 데이터가 8개 일 경우, 중간 값이 피벗으로 선택되면 8개, 4개, 2개, 1개 순으로 3번에 걸쳐 데이터가 분할됩니다. 이는 n개의 데이터가 1개로 분할되기까지 $\log{n}$으로 표현할 수 있습니다. 분할의 횟수는 $\log{n}$이고, 분할될 때마다 각각 n번의 비교 연산이 이루어져 최선의 경우는 $O(n\log{n})$의 시간 복잡도를 가집니다.&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;&lt;b&gt;자바스크립트 코드&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1631506516798&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function quickSort(arr){
  if(arr.length &amp;lt; 2){
    return arr;
  }
  
  let pivot = arr[0];
  let left = [];
  let right = [];
  
  for(let i = 1; i &amp;lt; arr.length; i++){
    if(arr[i] &amp;lt; pivot){
      left.push(arr[i]);
    }
    else if(arr[i] &amp;gt; pivot){
      right.push(arr[i]);
    }
    else{
      pivot.push(arr[i]);
    }
  }
  console.log(`left: ${left}, pivot: ${pivot}, right: ${right}`);
  return quickSort(left).concat(pivot, quickSort(right));
}

console.log(quickSort([13, 1, 3, 7, 9, 11, 5]));&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;b&gt;장점&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도가 &amp;nbsp;$O(n\log{n})$인 다른 알고리즘들과 비교했을 때 속도가 빠르다는 장점을 가지고 있습니다.&lt;/li&gt;
&lt;li&gt;제자리 정렬로 다른 추가적인 메모리가 필요하지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/h3&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;퀵 정렬은 다른 알고리즘들에 비해 빈번하게 사용되고, 효율적인 알고리즘입니다. 그러나&amp;nbsp;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;퀵 정렬의 불균형 분할을 방지하기 위하여 피벗을 선택할 때, 데이터들을 균등하게 분할할 수 있는 원소를 선택해야 특징을 가집니다. 실제 사용할 때 이점을 꼭 기억하고 사용합시다! : )&lt;/span&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <category>Algorithm</category>
      <category>quick sort</category>
      <category>알고리즘</category>
      <category>자바스크립트</category>
      <category>퀵 정렬</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/21</guid>
      <comments>https://oagree0123.tistory.com/entry/%ED%80%B5-%EC%A0%95%EB%A0%AC-Quick-Sort#entry21comment</comments>
      <pubDate>Mon, 13 Sep 2021 14:36:37 +0900</pubDate>
    </item>
    <item>
      <title>병합 정렬 (Merge Sort)</title>
      <link>https://oagree0123.tistory.com/entry/%EB%B3%91%ED%95%A9-%EC%A0%95%EB%A0%AC-Merge-Sort</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;병합 정렬&lt;/b&gt;&lt;/h3&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;&lt;b&gt;1) 분할 정복&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분할 정복은 문제를 2개의 문제로 분리하여 각각 해결하고, 결과를 모아 원래의 문제를 해결하는 전략입니다.&amp;nbsp;&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-origin-width=&quot;480&quot; data-origin-height=&quot;329&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o2F7w/btreXo6QOIO/ewoSrVIIknsUwpwHBK6cO0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o2F7w/btreXo6QOIO/ewoSrVIIknsUwpwHBK6cO0/img.gif&quot; data-alt=&quot;https://visualgo.net/en/sorting&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o2F7w/btreXo6QOIO/ewoSrVIIknsUwpwHBK6cO0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/o2F7w/btreXo6QOIO/ewoSrVIIknsUwpwHBK6cO0/img.gif&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;329&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://visualgo.net/en/sorting&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 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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;분할(Divide) : 배열을 동일한 크기의 배열 2개로 분할한다.&lt;/li&gt;
&lt;li&gt;정복(Conquer) : 분할된 배열을 조건에 맞게 정렬한다. 분할된 배열의 크기가 충분히 작지 않으면 재귀 호출로 다시 분할 정복 과정을 거친다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;결합(Combine) : 정렬된 배열들을 다시 결합한다.&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;&lt;b&gt;시간 복잡도&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;병합 정렬의 시간 복잡도는 예를들어 설명하겠습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;341&quot; data-filename=&quot;캡처.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cVa6ww/btreLJSzJGM/kJo0mBBoeIUtI3dRY0YDy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cVa6ww/btreLJSzJGM/kJo0mBBoeIUtI3dRY0YDy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cVa6ww/btreLJSzJGM/kJo0mBBoeIUtI3dRY0YDy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcVa6ww%2FbtreLJSzJGM%2FkJo0mBBoeIUtI3dRY0YDy0%2Fimg.png&quot; data-origin-width=&quot;557&quot; data-origin-height=&quot;341&quot; data-filename=&quot;캡처.PNG&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약, 데이터가 8개 일 경우, 중간 값이 피벗으로 선택되면 8개, 4개, 2개, 1개 순으로 3번에 걸쳐 데이터가 분할됩니다. 이는 n개의 데이터가 1개로 분할되기까지 $\log{n}$으로 표현할 수 있습니다. 분할의 횟수는 $\log{n}$이고, 분할될 때마다 각각 n번의 비교 연산이 이루어져 최선의 경우는 $O(n\log{n})$의 시간 복잡도를 가집니다.&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;&lt;b&gt;자바스크립트 코드&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1631510425215&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function mergeSort(arr){
  if(arr.length &amp;lt; 2){
    return arr;
  }
  let mid = Math.floor(arr.length / 2);
  let left = arr.slice(0, mid);
  let right = arr.slice(mid, arr.lenght);
  
  return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right){
  let result = [];
  
  while(left.length &amp;amp;&amp;amp; right.length){
    if(left[0] &amp;lt;= right[0]){
      result.push(left.shift());
    }
    else {
      result.push(right.shift());
    }
  }
  while(left.length){
    result.push(left.shift());
  }
  while(right.length){
    result.push(right.shift());
  }
  return result;
}

console.log(mergeSort([13, 1, 3, 7, 9, 11, 5]));&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;b&gt;장점&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최선의 경우와 최악의 경우 모두 $O(n\log{n})$으로 입력 데이터에 영향을 덜 받는 알고리즘입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/h3&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;병합 정렬은 퀵 정렬과 비교하여 많이 설명되는 정렬입니다. 병합 정렬을 이해한다면, 이후 퀵 정렬을 이해하시는데 도움이 될 것입니다. 병합 정렬의 분할, 정복 결합의 과정을 이해하고 넘어가시면 좋을 것 같습니다. : &amp;gt;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/22</guid>
      <comments>https://oagree0123.tistory.com/entry/%EB%B3%91%ED%95%A9-%EC%A0%95%EB%A0%AC-Merge-Sort#entry22comment</comments>
      <pubDate>Mon, 13 Sep 2021 14:36:22 +0900</pubDate>
    </item>
    <item>
      <title>삽입 정렬 (Insertion Sort)</title>
      <link>https://oagree0123.tistory.com/entry/%EC%82%BD%EC%9E%85-%EC%A0%95%EB%A0%AC-Insertion-Sort</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;script&gt; MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} }; &lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;삽입 정렬&lt;/b&gt;&lt;/h3&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;150&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vcS4k/btreLf4OT6Y/utQywsDeT1wJFhcy4G5P6k/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vcS4k/btreLf4OT6Y/utQywsDeT1wJFhcy4G5P6k/img.gif&quot; data-alt=&quot;https://visualgo.net/en/sorting&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vcS4k/btreLf4OT6Y/utQywsDeT1wJFhcy4G5P6k/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/vcS4k/btreLf4OT6Y/utQywsDeT1wJFhcy4G5P6k/img.gif&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;150&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://visualgo.net/en/sorting&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 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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;두 번째 자료에서 시작하여 앞의 원소들과 비교해 삽입할 위치를 정합니다.&lt;/li&gt;
&lt;li&gt;삽입될 위치가 정해지면, 뒤쪽의 원소들을 한 칸씩 뒤로 이동시킵니다.&lt;/li&gt;
&lt;li&gt;원소를 정해진 위치에 삽입합니다.&lt;/li&gt;
&lt;/ol&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;&lt;b&gt;시간 복잡도&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최악의 경우 selection sort와 마찬가지로, $O(n^2)$의 시간 복잡도를 가집니다. 수식으로 나타내면 아래와 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ (n-1) + (n-2) + ... + 2 + 1 = {n(n-1)} / {2} $$&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 모두 정렬이 되어 있는 경우, 한 번씩만 비교하기 때문에 $O(n)$의 시간 복잡도를 가집니다.&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;&lt;b&gt;자바스크립트 코드&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1631497447358&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function insertSort(arr) {
  for(let i = 1; i &amp;lt; arr.length; i++){
  	let temp = arr[i];
    let left = i - 1;
    
	while(left &amp;gt;= 0 &amp;amp;&amp;amp; arr[left] &amp;gt; temp) {
      arr[left + 1] = arr[left];
      left--;
    }
    
    arr[left + 1] = temp;
  }
  
  return arr;
}

console.log(insertSort([1, 5, 7, 3, 9]));&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/h3&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;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최악의 경우 $O(n^2)$로 비효율적입니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삽입 정렬은 선택 정렬과 유사한 부분이 많습니다. n 회차 이후에 n번째 자리가 정렬되는 공통점을 가지고 있습니다. 또한, 삽입 정렬의 특징은 버블 정렬, 선택 정렬과 많은 부분이 비슷합니다. 세 정렬을 비슷한 부분이 많은 만큼 쉽게 이해할 수 있으니 한 번에 같이 공부하시면 좋을 것 같습니다. : )&lt;/p&gt;</description>
      <category>Algorithm</category>
      <category>Algorithm</category>
      <category>insertion sort</category>
      <category>삽입정렬</category>
      <category>알고리즘</category>
      <category>자바스크립트</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/20</guid>
      <comments>https://oagree0123.tistory.com/entry/%EC%82%BD%EC%9E%85-%EC%A0%95%EB%A0%AC-Insertion-Sort#entry20comment</comments>
      <pubDate>Mon, 13 Sep 2021 11:00:05 +0900</pubDate>
    </item>
    <item>
      <title>선택 정렬 (Selection sort)</title>
      <link>https://oagree0123.tistory.com/entry/%EC%84%A0%ED%83%9D-%EC%A0%95%EB%A0%AC-Selection-sort</link>
      <description>&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;&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;
&lt;script&gt; MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} }; &lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;선택 정렬&lt;/b&gt;&lt;/h3&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-origin-width=&quot;480&quot; data-origin-height=&quot;150&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BbTuY/btreCVEGwmc/3TmjwEYDlkyU63lrKxsKZk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BbTuY/btreCVEGwmc/3TmjwEYDlkyU63lrKxsKZk/img.gif&quot; data-alt=&quot;https://visualgo.net/en/sorting&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BbTuY/btreCVEGwmc/3TmjwEYDlkyU63lrKxsKZk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/BbTuY/btreCVEGwmc/3TmjwEYDlkyU63lrKxsKZk/img.gif&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;150&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://visualgo.net/en/sorting&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 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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;먼저, 데이터들 중에 최소값을 찾습니다.&lt;/li&gt;
&lt;li&gt;찾은 최소값을 맨 앞에 위치한 데이터와 교화합니다.&lt;/li&gt;
&lt;li&gt;정렬된 맨 앞의 값을 제외하고 위와 같은 방식으로 데이터의 위치를 교환합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택 정렬은 버블 정렬과 반대로 회전마다 맨 앞의 데이터를 제외합니다. 선택 정렬은 n번의 회전 마다 n번째 데이터의 위치가 정해집니다.&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;&lt;b&gt;시간 복잡도&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택 정렬은 버블 정렬과 마찬가지로 $O(n^2)$ 입니다. 한 번의 회전에 데이터 하나를 제외하기 때문에, 데이터가 n개 일 때, n-1 번의 순회가 필요합니다. 이를 수식으로 나타내면 아래와 같습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ (n-1) + (n-2) + ... + 2 + 1 = {n(n-1)} / {2} $$&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;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7534213975012335&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;p&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block; text-align: center;&quot; data-ad-layout=&quot;in-article&quot; data-ad-format=&quot;fluid&quot; data-ad-client=&quot;ca-pub-7534213975012335&quot; data-ad-slot=&quot;1383201687&quot;&gt;&lt;/ins&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&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;&lt;b&gt;자바스크립트 코드&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1631248805982&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function selectionSort(arr) {
  let minIndex;
  let swap;
  for(let i = 0; i &amp;lt; arr.length; i++){
     minIndex = i;
     for(let j = i + 1; j &amp;lt; arr.length; j++){
       if(arr[minIndex] &amp;gt; arr[j]){
         minIndex = j;
       }
     }
     swap = arr[minIndex];
     arr[minIndex] = arr[i];
     arr[i] = swap;
  }
  return arr;
}

console.log(selectionSort([5, 3, 9, 1, 7]));&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/h3&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도가 &amp;nbsp;$O(n^2)$로 많은 시간이 걸리고 비효율 적이다.&lt;/li&gt;
&lt;li&gt;수가 중복된 경우 위치가 바뀔 수 있는 불완전(Unstable) 정렬이다.&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;&lt;b&gt;정리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택 정렬은 버블 정렬과 유사한 부분이 많습니다. 그러나 선택 정렬은 맨 앞에서 부터 정렬된다는 특징이 있습니다. 그 외에 버블 정렬과 시간 복잡도나 제자리 정렬이라는 공통점을 가집니다. 앞서 버블 정렬을 읽고 오신다면, 선택 정렬도 금방 이해하실 것이라고 생각합니다! : &amp;gt;&lt;/p&gt;</description>
      <category>Algorithm</category>
      <category>Algorithm</category>
      <category>Selection Sort</category>
      <category>선택 정렬</category>
      <category>알고리즘</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/19</guid>
      <comments>https://oagree0123.tistory.com/entry/%EC%84%A0%ED%83%9D-%EC%A0%95%EB%A0%AC-Selection-sort#entry19comment</comments>
      <pubDate>Fri, 10 Sep 2021 13:59:09 +0900</pubDate>
    </item>
    <item>
      <title>버블 정렬 (Bubble Sort)</title>
      <link>https://oagree0123.tistory.com/entry/%EB%B2%84%EB%B8%94-%EC%A0%95%EB%A0%AC-Bubble-Sort</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;
&lt;script&gt; MathJax = { tex: {inlineMath: [['$', '$'], ['\\(', '\\)']]} }; &lt;/script&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js&quot;&gt;&lt;/script&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;&lt;b&gt;버블 정렬&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬(bubble sort)은 인접한 두 수를 비교하여 조건에 맞지 않으면 두 수의 자리를 교환하여 정렬하는 알고리즘입니다.&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-origin-width=&quot;480&quot; data-origin-height=&quot;150&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsYM0g/btreBkSkzLu/kbCSJC1kxDnHdXmpXHFC11/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsYM0g/btreBkSkzLu/kbCSJC1kxDnHdXmpXHFC11/img.gif&quot; data-alt=&quot;https://visualgo.net/en/sorting&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsYM0g/btreBkSkzLu/kbCSJC1kxDnHdXmpXHFC11/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bsYM0g/btreBkSkzLu/kbCSJC1kxDnHdXmpXHFC11/img.gif&quot; data-origin-width=&quot;480&quot; data-origin-height=&quot;150&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;https://visualgo.net/en/sorting&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 data-ke-size=&quot;size16&quot;&gt;오름차순으로 정렬하는 위의 그림을 보면, 첫 번째 데이터와 두 번째 데이터를 비교하여 크기가 큰 데이터를 오른쪽의 자리로 교환하는 것을 볼 수 있습니다. 이후 두 번째와 세 번째, 다시 세 번째와 네 번째 ... 한 칸씩 이동하면서 조건이 맞지 않으면 서로의 자리를 교환합니다. 1회전이 끝나면 가장 큰 수가 맨 뒤에 위치하기 때문에 맨 끝 데이터는 정렬에서 제외됩니다. n회전에서 n개의 데이터가 정렬이 되었다고 판단하기 때문에, 뒤에서 n개의 데이터를 정렬에서 제외합니다.&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;&lt;b&gt;시간 복잡도&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬은 최악의 경우에 $O(n^2)$의 시간 복잡도를 가집니다. 버블 정렬은 한 번의 회전에 데이터 하나를 제외하기 때문에, 데이터가 n개 일 때, n-1 번의 순회가 필요합니다. 이를 수식으로 나타내면 아래와 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;$$ (n-1) + (n-2) + ... + 2 + 1 = {n(n-1)} / {2} $$&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;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-7534213975012335&quot;&gt;&lt;/script&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;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;자바스크립트 코드&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1631239176569&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function bubbleSort(arr) {
  let swap;
  for(let i = 0; i &amp;lt; arr.length; i++) {
    for(let j = 0; j &amp;lt; arr.length - 1; j++){
      if(arr[j] &amp;gt; arr[j+1]) {
        swap = arr[j];
        arr[j] = arr[j+1];
        arr[j+1] = swap;
      }
    } 
  }
  return arr;
}

console.log(bubbleSort([5, 3, 9, 7, 1]));&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/h3&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;span style=&quot;color: #000000;&quot;&gt;(in-place sorting)&lt;/span&gt;, 이미 존재하는 배열 안에서 교환이 이루어 지므로, 다른 메모리 공간이 필요하지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;$O(n^2)$이라는 시간 복잡도로 데이터의 개수가 늘어날수록 성능이 많이 저하됩니다.&lt;/li&gt;
&lt;li&gt;정렬되어있지 않은 데이터를 교환(swap)하는 연산이 많이 발생합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버블 정렬은 직관적인 코드와 쉬운 구현에도 불구하고 잘 사용되지 않습니다. 시간 복잡도로 인해 데이터가 많으면 많을수록 성능이 급격하게 저하됩니다. 그래도 정렬에 대한 기본 개념을 익히기 좋으며, 쉽게 이해할 수 있기 때문에 알아두시면 좋을 것 같습니다! : )&lt;/p&gt;</description>
      <category>Algorithm</category>
      <category>Algorithm</category>
      <category>Bubble Sort</category>
      <category>거품 정렬</category>
      <category>버블 정렬</category>
      <category>알고리즘</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/18</guid>
      <comments>https://oagree0123.tistory.com/entry/%EB%B2%84%EB%B8%94-%EC%A0%95%EB%A0%AC-Bubble-Sort#entry18comment</comments>
      <pubDate>Fri, 10 Sep 2021 10:39:46 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 화살표 함수 (Arrow Function)</title>
      <link>https://oagree0123.tistory.com/entry/JavaScript-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98-Arrow-Function</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;화살표 함수는 ES6부터 사용되는 문법입니다. function을 사용하여 함수를 만드는 것보다 간단하게 함수를 작성할 수 있는 장점이 있습니다. 오늘은 화살표 함수에 대해 알아보겠습니다. \'_'/&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 화살표 함수&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, 기존의 함수와 화살표 함수의 작성 방법에 대해 보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1631082333295&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var a = function() {
	// 내용
};

var a = () =&amp;gt; {
	//내용
};&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;b&gt;화살표 함수 특징&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;화살표 함수는 &lt;span style=&quot;background-color: #f8f9fa; color: #212529;&quot;&gt;자신의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;t&lt;/b&gt;his, arguments, super 또는 new.target을 바인딩 하지 않습니다&lt;span style=&quot;background-color: #f8f9fa; color: #212529;&quot;&gt;. &lt;/span&gt;화살표 함수는 항상 익명 함수 입니다. 화살표 함수는 메소드 함수가 아닌 곳에 적합하기 때문에 생성자로는 사용할 수 없습니다. - MDN&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;&lt;b&gt;2. 화살표 함수의 기본 문법&lt;/b&gt;&lt;/h3&gt;
&lt;pre id=&quot;code_1631083048265&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 매개 변수가 없는 화살표 함수
var foo = () =&amp;gt; {
    console.log(&quot;test&quot;);
};

// 매개 변수가 있는 화살표 함수
var foo = (a, b) =&amp;gt; {
    return a + b;
};
foo(1, 2) // 3

// return이 없는 경우
var foo = (a, b) =&amp;gt; {
    a + b;
};
foo(1, 2) // undefined

// 콜백 함수
var nums = [1, 2, 3, 4, 5];
var makeArr = nums.map( x =&amp;gt; x + 1);

console.log(makeArr); // [2, 3, 4, 5, 6]&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;b&gt;3. 화살표 함수 this&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;함수를 호출하는 방법에 의해 결정되었던 일반 함수의 this와 달리 화살표 함수의 this는 선언되는 시점에 결정되며, 상위 스코프의 this를 가리킵니다. 코드를 통해 보겠습니다.&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631085389548&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var name = 'Park';

var test1 = {
    name: 'Kim',
    printName: function() {
        console.log(this.name);
    }
};

test1.printName(); // 'Kim'

var test2 = {
    name: 'Lee',
    printName: () =&amp;gt; {
        console.log(this.name);
    }
};

test2.printName(); // 'Park'&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 이런 결과가 나왔을까요? 위에서 말했듯이 화살표 함수의 this는 상위 스코프의 this를 가리켜 window를 가리키고 있습니다. 따라서 전역 변수 name을 가리키고 Park이라는 값을 보여주게 됩니다.&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>JavaScript</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/17</guid>
      <comments>https://oagree0123.tistory.com/entry/JavaScript-%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98-Arrow-Function#entry17comment</comments>
      <pubDate>Wed, 8 Sep 2021 16:21:18 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 클로저 (Closure)</title>
      <link>https://oagree0123.tistory.com/entry/JavaScript-%ED%81%B4%EB%A1%9C%EC%A0%80-Closure</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;클로저는 스코프(Scope)에 대해 이해하고 있지 않으시다면, 클로저도 이해하시기 힘드실 것입니다. 이 글을 읽기전에 스코프에 대해 공부하시고 오시는 것을 추천 드립니다. : )&lt;/span&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;&lt;b&gt;1. 클로저&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;MDN에서는 &quot;클로저는&amp;nbsp;함수와 함수가&amp;nbsp;선언된 어휘적 환경(lexical scope)&amp;nbsp;의 조합이다.&quot;라고 정의하고 있습니다. 조금 풀어서 설명하자면, 클로저는 외부 함수의 실행이 끝나 함수가 소멸되어도 내부 함수가 외부 함수의 변수에 접근할 수 있는 것을 말합니다. 역시 글로만 설명하니 무슨 이야기인지 정확하게 이해하기 힘듭니다. 설명을 위해 아래의 코드를 보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631076734412&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function ex() {
    var id = '01';
    
    function inner() {
        console.log(id);
    }
    return inner;
}

var check = ex();
check(); // 01&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 ex() 함수가 리턴되어 사라진 후에 내부 함수 inner()가 생성되었는데, 내부 함수에서 외부 함수의 지역 변수에 접근한 것을 볼 수 있습니다. 이처럼 외부 함수가 사라지지 않고 내부 함수의 참조를 위해 값이 유지되는 것을 클로저라고 합니다.&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;조금 더 자세하게 보겠습니다. 먼저 ex()를 출력한 결과가 무엇일까요?&lt;/p&gt;
&lt;pre id=&quot;code_1631077552295&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(ex());

//결과
&amp;fnof; inner() {
        console.log(id);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex() 함수는 inner 함수를 return 하고 있습니다. 또한, 변수 check는 반환된 ex() 함수를 참조하고 있습니다. 일반적으로 함수 내부의 지역 변수는 함수의 실행이 종료되면 파기되는데, 클로저 함수에 의해 참조되는 경우에는 지역 변수를 파기하지 않고 계속 보관하고 있는 것입니다. 따라서, innder() 함수에는 변수 id가 없기 때문에 에러가 날 것이라고 생각되었지만 클로저에 의해 실행되는 것을 알 수 있습니다.&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;&lt;b&gt;2. 함수의 캡슐화(은닉화)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;클로저를 이용하면 함수의 변수를 외부에서 함부로 바꿀 수 없는 private한 변수로 만들 수 있습니다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1631079670588&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function user(name) {
    return {
        setName: function(_name) {
            name = _name;
        },
        getName: function() {
            return name;
        }
    }
}

var Kim = user(&quot;Kim&quot;);
var Lee = user(&quot;Lee&quot;);

Lee.setName(&quot;Park&quot;);

console.log(Kim.getName());
console.log(Lee.getName());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드처럼 클로저를 사용하면 name을 변경하는 기능을 만들지 않는 이상, 외부에서 name을 변경할 수 없습니다.&lt;/p&gt;</description>
      <category>JavaScript</category>
      <category>closure</category>
      <category>JavaScript</category>
      <category>자바스크립트</category>
      <category>클로저</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/16</guid>
      <comments>https://oagree0123.tistory.com/entry/JavaScript-%ED%81%B4%EB%A1%9C%EC%A0%80-Closure#entry16comment</comments>
      <pubDate>Wed, 8 Sep 2021 15:00:13 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] 스코프 (Scope)</title>
      <link>https://oagree0123.tistory.com/entry/JavaScript-%EC%8A%A4%EC%BD%94%ED%94%84-Scope</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;스코프는 번역하면 '범위'라는 뜻을 가지고 있습니다. 이것이 자바스크립트에서 어떠한 것을 의미하는지 알아보겠습니다. : )&lt;/span&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;&lt;b&gt;1. 스코프 (Scope)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스코프는 전역(Global) 스코프과 지역(Local) 스코프 두 가지로 나눌 수 있습니다. 전역 스코프는 어느 곳에서든지 참조할 수 있는 것을 말합니다. 지역 스코프는 정의된 지역(함수) 안에서만 참조될 수 있는 것을 말합니다.&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;코드를 보고 조금 더 설명하겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1631064564596&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var a = 'global';

function test() {
    var a = 'local';
    console.log(a);
}

test();         // local
console.log(a); // global&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 함수 밖에 선언된 변수 a는 전역 변수이고, 함수 내부에 선언된 변수 a는 지역 변수입니다. 함수 내에서 변수 a에 'local'이라는 값을 대입했어도 함수 밖에서 변수 a는 전역 변수를 참조하는 것을 볼 수 있습니다.&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;&lt;b&gt;2. 함수 스코프&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수 스코프는 ES6이전에 자바스크립트에서 적용되는 스코프입니다. 함수 스코프는 함수 내부에 선언한 변수는 지역 변수이고, 함수 외부에 선언한 함수는 모두 전역 변수입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1631066376637&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var name = 'Kim'

{
    var name = 'park';
}

function userCheck() {
    var name = 'Lee';
    var age = '20';
    
    console.log(`name: ${name}, age: ${age}`);
}

userCheck();       // name: Lee, age: 20
console.log(name); // park&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 보면 함수 내부의 name은 설명한데로 지역 변수인 것을 확인할 수 있지만, {} 안에 있는 변수 name이 전역 변수로 적용되는 것을 볼 수 있습니다.&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;&lt;b&gt;3. 블록 스코프&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록 스코프는 ES6이후 let과 const가 나타나면서 적용되는 스코프입니다. {}의 내부에 선언된 변수는 지역 변수로 취급하는 것을 말합니다. 위의 코드를 조금 바꿔서 한번 살펴보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1631066695564&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let name = 'Kim'

{
    let name = 'park';
}

function userCheck() {
    let name = 'Lee';
    let age = '20';
    
    console.log(`name: ${name}, age: ${age}`);
}

userCheck();       // name: Lee, age: 20
console.log(name); // Kim&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 var을 사용한 코드에는 'park'으로 변수의 값이 변했지만, let을 사용하면 {}안의 변수는 지역 변수로 적용되어 전역 변수 name의 값이 변경되지 않는 것을 볼 수 있습니다.&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;&lt;b&gt;4. 렉시컬 스코프&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스코프는 함수를 어디서 호출하는지가 중요한 것이 아니라 함수를 선언했을 때 생깁니다. 이번에도 코드를 보고 설명하겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1631067325288&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let a = 10;

function test() {
    let a = 20;
    print();
}

function print() {
    console.log(a);
}

test();
print();&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;정답은, 둘다 10이 나오게 됩니다. 위에서 설명했듯 함수가 선언될 때 스코프가 결정됩니다. print() 함수는 전역에 선언되었기 때문에 전역 변수 a를 참조하여 값을 보여줍니다.&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;&lt;b&gt;5. 스코프 체인&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스코프 체인은 내부 함수에서 변수를 찾고, 변수가 없다면 상위 스코프에서 변수를 다시 찾는 것을 말합니다. 즉, 내부 함수는 외부 함수의 변수를 접근할 수 있지만, 외부 함수는 내부 함수의 변수에 접근할 수 없습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1631075306830&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let id = 01;

function ex() {
    console.log(id);
    function in() {
        var innerId = 02;
        console.log(id);
    }
    in();
}

ex();  // 01
console.log(innderId);  / undefined&lt;/code&gt;&lt;/pre&gt;</description>
      <category>JavaScript</category>
      <category>JavaScript</category>
      <category>scope</category>
      <category>스코프</category>
      <category>자바스크립트</category>
      <category>전역변수</category>
      <category>지역변수</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/14</guid>
      <comments>https://oagree0123.tistory.com/entry/JavaScript-%EC%8A%A4%EC%BD%94%ED%94%84-Scope#entry14comment</comments>
      <pubDate>Wed, 8 Sep 2021 11:19:38 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] async/await</title>
      <link>https://oagree0123.tistory.com/entry/JavaScript-asyncawait</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 처리의 마지막 부분입니다. async/await을 이해하기 위해서는 앞의 글을 읽고오셔야 이해가 가능할거 같습니다. 어짜피 알아야 하는 내용이니까 한 번씩 읽고 오시는 것을 추천드립니다.&amp;nbsp; &amp;nbsp;\('_')/&lt;/p&gt;
&lt;figure id=&quot;og_1630897040858&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] 비동기 처리&quot; data-og-description=&quot;아래의 그림을 보면 동기적 처리와 비동기적 처리를 간단하게 확인할 수 있습니다. 대충 이해가 가시나요? 그림만 보고 정확하게 이해하기는 힘드니 어떤 상황에 사용하는지 어떤 의미인지 알&quot; data-og-host=&quot;oagree0123.tistory.com&quot; data-og-source-url=&quot;https://oagree0123.tistory.com/11&quot; data-og-url=&quot;https://oagree0123.tistory.com/11&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/VQpnA/hyLuTHVxLn/USaKmPfPU6ON1Zgrvgb29k/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/IAC2X/hyLwp6ihSb/V46sFiXk7GZFNdGnXzUhi1/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/beHJSr/hyLwfo4IlT/HTCa7BRhiq4D1JK9FTtoM1/img.png?width=1600&amp;amp;height=900&amp;amp;face=0_0_1600_900&quot;&gt;&lt;a href=&quot;https://oagree0123.tistory.com/11&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://oagree0123.tistory.com/11&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/VQpnA/hyLuTHVxLn/USaKmPfPU6ON1Zgrvgb29k/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/IAC2X/hyLwp6ihSb/V46sFiXk7GZFNdGnXzUhi1/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/beHJSr/hyLwfo4IlT/HTCa7BRhiq4D1JK9FTtoM1/img.png?width=1600&amp;amp;height=900&amp;amp;face=0_0_1600_900');&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] 비동기 처리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;아래의 그림을 보면 동기적 처리와 비동기적 처리를 간단하게 확인할 수 있습니다. 대충 이해가 가시나요? 그림만 보고 정확하게 이해하기는 힘드니 어떤 상황에 사용하는지 어떤 의미인지 알&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;oagree0123.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;figure id=&quot;og_1630897048094&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] Promise&quot; data-og-description=&quot;이전 글에서 비동기 처리를 위해 콜백 함수를 사용했습니다. 그런데 콜백 함수를 사용하면 비동기 처리 작업이 많아질 수록 코드가 복잡해지는 것을 볼 수 있었습니다. 이번에는 이를 해결하는 &quot; data-og-host=&quot;oagree0123.tistory.com&quot; data-og-source-url=&quot;https://oagree0123.tistory.com/12&quot; data-og-url=&quot;https://oagree0123.tistory.com/12&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Bgj57/hyLwbNOaDd/kMafH94n5F4fROPa6ozGSk/img.png?width=800&amp;amp;height=296&amp;amp;face=0_0_800_296,https://scrap.kakaocdn.net/dn/b2vzkH/hyLuR4uEaQ/uEEpzlgj1lZA2KpaAnDpLK/img.png?width=800&amp;amp;height=296&amp;amp;face=0_0_800_296,https://scrap.kakaocdn.net/dn/bCAQ6W/hyLwfJq7sx/pOJLqQVgo4rEhs1vj1AIa1/img.png?width=801&amp;amp;height=297&amp;amp;face=0_0_801_297&quot;&gt;&lt;a href=&quot;https://oagree0123.tistory.com/12&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://oagree0123.tistory.com/12&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Bgj57/hyLwbNOaDd/kMafH94n5F4fROPa6ozGSk/img.png?width=800&amp;amp;height=296&amp;amp;face=0_0_800_296,https://scrap.kakaocdn.net/dn/b2vzkH/hyLuR4uEaQ/uEEpzlgj1lZA2KpaAnDpLK/img.png?width=800&amp;amp;height=296&amp;amp;face=0_0_800_296,https://scrap.kakaocdn.net/dn/bCAQ6W/hyLwfJq7sx/pOJLqQVgo4rEhs1vj1AIa1/img.png?width=801&amp;amp;height=297&amp;amp;face=0_0_801_297');&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] Promise&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이전 글에서 비동기 처리를 위해 콜백 함수를 사용했습니다. 그런데 콜백 함수를 사용하면 비동기 처리 작업이 많아질 수록 코드가 복잡해지는 것을 볼 수 있었습니다. 이번에는 이를 해결하는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;oagree0123.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. async / await&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;async / await 은 자바스크립트 비동기 처리에서 가장 최근에 나온 방법입니다. 이전에 보았던 콜백 함수와 Promise의 단점을 보완해주는 특징을 가지고 있습니다.&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;pre id=&quot;code_1630905907752&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async function 함수명() {
	await 비동기 처리 메서드 명();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 비동기 처리 메서드는 Promise 객체를 반환해야 await이 적확히 작동합니다.&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;pre id=&quot;code_1630906525819&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function testFunc() {
	return new Promise(function(resolve, reject) {
    	var Nums = [0, 1];
        resolve(Nums);
    });
}

async function printNum() {
	var result = await testFunc();
    console.log(result);
}

printNum(); // [0, 1]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 async / await을 사용하지 않았다면 어떻게 되었을까요? 데이터를 받아온 후에 출력을 하고 싶다면, 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;간단한 예제를 하나만 더 보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1630909362019&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function getUser() {
	var user = {
    	id : 1,
        name : &quot;Kim&quot;,
    };
    return new Promise(function(resolve, reject){
    	resolve(user);
    });
}

async function test() {
    var na = await getUser();
    if(na.id === 1) {
    	console.log(na.name);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서는 임의로 만든 객체의 id와 name을 가져왔습니다. 이를 응용하면 만들어진 객체가 아닌 json이나 xml 형태의 유저의 정보를 가져올 수 있을 것입니다.&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;&lt;b&gt;2. async / await 예외처리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;async / await 예외처리 방법은 try / catch 입니다. 이번에도 예제로 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1630909817039&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function getUser() {
	var user = {
    	id : 1,
        name : &quot;Kim&quot;,
    };
    return new Promise(function(resolve, reject){
    	resolve(user);
    });
}

async function test() {
	try{
        var na = await getUser();
        if(na.id === 1) {
            console.log(na.name);
        }
    } catch (error) {
    	console.log(error);
    }
}&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;콜백 함수, 비동기 처리 개념, Promise, async/await 까지 한 번에 이해하기가 쉽지는 않습니다. 그래도 서비스를 하기 위해서는 꼭 필요한 내용이니 공부합시다!! 지금 당장 이해가 안되신 분들은 나중에 본인의 코드에 적용하시면서 다시 공부해 보시는 것을 추천드립니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;참고 문서&lt;/b&gt;&lt;/h3&gt;
&lt;figure id=&quot;og_1630910078938&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;자바스크립트 async와 await&quot; data-og-description=&quot;(중급) 자바스크립트 개발자를 위한 async, await 사용법 설명. 쉽게 알아보는 자바스크립트 async await 개념, 사용법, 예제 코드, 예외 처리 방법&quot; data-og-host=&quot;joshua1988.github.io&quot; data-og-source-url=&quot;https://joshua1988.github.io/web-development/javascript/js-async-await/&quot; data-og-url=&quot;https://joshua1988.github.io/web-development/javascript/js-async-await/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cw0w5g/hyLwfQiT93/jaFtVufmVuxLVvgM71cfJ0/img.png?width=646&amp;amp;height=450&amp;amp;face=0_0_646_450,https://scrap.kakaocdn.net/dn/BWBAe/hyLwpFomiE/B3v30pgBqoKOTxCcYuLKak/img.png?width=461&amp;amp;height=460&amp;amp;face=0_0_461_460&quot;&gt;&lt;a href=&quot;https://joshua1988.github.io/web-development/javascript/js-async-await/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://joshua1988.github.io/web-development/javascript/js-async-await/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cw0w5g/hyLwfQiT93/jaFtVufmVuxLVvgM71cfJ0/img.png?width=646&amp;amp;height=450&amp;amp;face=0_0_646_450,https://scrap.kakaocdn.net/dn/BWBAe/hyLwpFomiE/B3v30pgBqoKOTxCcYuLKak/img.png?width=461&amp;amp;height=460&amp;amp;face=0_0_461_460');&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;자바스크립트 async와 await&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;(중급) 자바스크립트 개발자를 위한 async, await 사용법 설명. 쉽게 알아보는 자바스크립트 async await 개념, 사용법, 예제 코드, 예외 처리 방법&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;joshua1988.github.io&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;</description>
      <category>JavaScript</category>
      <category>await</category>
      <category>JavaScript</category>
      <category>Promise</category>
      <category>비동기처리</category>
      <category>자바스크립트</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/13</guid>
      <comments>https://oagree0123.tistory.com/entry/JavaScript-asyncawait#entry13comment</comments>
      <pubDate>Mon, 6 Sep 2021 15:34:45 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript] Promise</title>
      <link>https://oagree0123.tistory.com/entry/JavaScript-Promise</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이전 글에서 비동기 처리를 위해 콜백 함수를 사용했습니다. 그런데 콜백 함수를 사용하면 비동기 처리 작업이 많아질 수록 코드가 복잡해지는 것을 볼 수 있었습니다. 이번에는 이를 해결하는 Promise 사용법에 대해 알아보겠습니다.&lt;/p&gt;
&lt;figure id=&quot;og_1630890540809&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] 비동기 처리&quot; data-og-description=&quot;아래의 그림을 보면 동기적 처리와 비동기적 처리를 간단하게 확인할 수 있습니다. 대충 이해가 가시나요? 그림만 보고 정확하게 이해하기는 힘드니 어떤 상황에 사용하는지 어떤 의미인지 알&quot; data-og-host=&quot;oagree0123.tistory.com&quot; data-og-source-url=&quot;https://oagree0123.tistory.com/11&quot; data-og-url=&quot;https://oagree0123.tistory.com/11&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/VQpnA/hyLuTHVxLn/USaKmPfPU6ON1Zgrvgb29k/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/IAC2X/hyLwp6ihSb/V46sFiXk7GZFNdGnXzUhi1/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/beHJSr/hyLwfo4IlT/HTCa7BRhiq4D1JK9FTtoM1/img.png?width=1600&amp;amp;height=900&amp;amp;face=0_0_1600_900&quot;&gt;&lt;a href=&quot;https://oagree0123.tistory.com/11&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://oagree0123.tistory.com/11&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/VQpnA/hyLuTHVxLn/USaKmPfPU6ON1Zgrvgb29k/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/IAC2X/hyLwp6ihSb/V46sFiXk7GZFNdGnXzUhi1/img.png?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/beHJSr/hyLwfo4IlT/HTCa7BRhiq4D1JK9FTtoM1/img.png?width=1600&amp;amp;height=900&amp;amp;face=0_0_1600_900');&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] 비동기 처리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;아래의 그림을 보면 동기적 처리와 비동기적 처리를 간단하게 확인할 수 있습니다. 대충 이해가 가시나요? 그림만 보고 정확하게 이해하기는 힘드니 어떤 상황에 사용하는지 어떤 의미인지 알&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;oagree0123.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. Promise&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise는 자바스크립트에서 비동기 처리를 위해 사용되는 객체입니다. Promise는 성공을 할 수도 있고, 실패를 할 수도 있습니다. 성공을 하면 resolve를 호출하고, 실패하면 reject를 호출합니다.&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;b&gt;프로미스 생성, 실행&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 Promise를 생성하고 실행하는 예제 코드를 보겠습니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1630892025284&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 프로미스 생성
const testPromise = function(param) {
	return new Promise(function(resolve, reject){
    	if(param){
        	resolve(&quot;성공&quot;);
        }
        else {
        	reject(&quot;실패&quot;);
        }
    });
}

// 프로미스 실행
testPromise(true)  // true or false
.then(function(result){
	console.log(result); // 성공
})
.catch(function(err) {
	console.log(err); // 실패
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new로 Promise 객체를 생성하고, resolve(), reject() 함수로 Promise를 생성합니다. Promise를 실행하는 부분에는 then(), catch() 함수가 있습니다. 아래에서는 각각 어떤 역할을 하는지 보겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. Promise의 상태&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise에는 3가지 상태가 있는데 이는 Promise의 처리 과정을 의미합니다. 위 코드를 세부적으로 나눠 상태를 확인해 보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 78.7209%; height: 111px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 26.7442%; height: 20px; text-align: center;&quot;&gt;Pending (대기)&lt;/td&gt;
&lt;td style=&quot;width: 73.2558%; height: 20px; text-align: center;&quot;&gt;비동기 처리 로직을 아직 수행하는 상태&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 26.7442%; height: 20px; text-align: center;&quot;&gt;Fulfilled (이행)&lt;/td&gt;
&lt;td style=&quot;width: 73.2558%; height: 20px; text-align: center;&quot;&gt;비동기 처리 로직이 완료되어 값을 반환한 상태&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 26.7442%; height: 20px; text-align: center;&quot;&gt;Rejected (실패)&lt;/td&gt;
&lt;td style=&quot;width: 73.2558%; height: 20px; text-align: center;&quot;&gt;비동기 처리가 어떠한 이유에서 실패한 상태&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;b&gt;Pending (대기)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new Promise()로 객체를 생성하게 되면 맨 처음 대기 상태가 되고, resolve와 reject를 파라미터로 받는 익명함수를 사용합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1630893645673&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;new Promise(function(resolve, reject){});&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Fulfilled (이행)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;익명 함수의 resolve를 실행하여 결과를 받게되면 Fulfilled 상태가 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1630894044337&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;
const testPromise = function(param) {
	return new Promise(function(resolve, reject){
    	if(param){
        	resolve(&quot;성공&quot;);
        }
        else {
        	reject(&quot;실패&quot;);
        }
    });
}

testPromise(true).then(function(result){
	console.log(result); // 성공
});&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Rejected (실패)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;익명 함수의 reject를 실행하여 어떠한 이유로 실패하게 되는 상태입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1630894227873&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const testPromise = function(param) {
	return new Promise(function(resolve, reject){
    	if(param){
        	resolve(&quot;성공&quot;);
        }
        else {
        	reject(&quot;실패&quot;);
        }
    });
}

testPromise(false)  
.then(function(result){
	console.log(result); // 성공
})
.catch(function(err) {
	console.log(err); // 실패
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체적인 프로세스를 설명하면,&amp;nbsp;Promise를 생성하는 부분을 보면 함수를 사용하여 Promise 객체를 리턴하고,&amp;nbsp; Promise 객체는 익명함수를 파라미터로 가지며, 익명 함수는 resolve와 reject를 파라미터로 받고 있는 형태 입니다. 이때 param으로 true 나 false가 오게 되는데 성공하면 resolve를 실행, 실패하면 reject를 실행하게 됩니다.&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;아래의 그림은 Promise의 상태와 프로세스를 그림으로 나타낸 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;801&quot; data-origin-height=&quot;297&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmhdco/btrd2942UoQ/b4NGjymoo90z5ulIfm3au0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmhdco/btrd2942UoQ/b4NGjymoo90z5ulIfm3au0/img.png&quot; data-alt=&quot;출처 : MDN Web Docs&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmhdco/btrd2942UoQ/b4NGjymoo90z5ulIfm3au0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdmhdco%2Fbtrd2942UoQ%2Fb4NGjymoo90z5ulIfm3au0%2Fimg.png&quot; data-origin-width=&quot;801&quot; data-origin-height=&quot;297&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : MDN Web Docs&lt;/figcaption&gt;
&lt;/figure&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;&lt;b&gt;3. Promise 체이닝&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise는 여러 개를 연결하여 사용할 수 있다는 특징을 가집니다. then() 내부에 Promise를 다시 리턴하게 된다면 연달아 사용되는 것을 볼 수 있습니다. setTimeout()을 사용하여 결과를 확인해 보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1630895385529&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function testPromise(param) {
	return new Promise(function(resolve, reject){
    	setTimeout(function() {
        	var result = param + 1;

            if(param === 3){
        		reject(&quot;초과&quot;);
        		return;
        	}
            console.log(result);
            resolve(result);
        }, 1000);
    });
}

testPromise(0)  
.then(function(param){
	return testPromise(param);
})
.then(function(param){
	return testPromise(param);
})
.then(function(param){
	return testPromise(param);
})
.catch(function(err) {
	console.log(err);
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 더 정리하면 아래와 같이 작성할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1630896029938&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function testPromise(param) {
	return new Promise(function(resolve, reject){
    	setTimeout(function() {
        	var result = param + 1;

            if(param === 3){
        		reject(&quot;초과&quot;);
        		return;
        	}
            console.log(result);
            resolve(result);
        }, 1000);
    });
}

testPromise(0)  
.then(testPromise)
.then(testPromise)
.then(testPromise)
.catch(function(err) {
	console.log(err);
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Promise를 사용하여 여러 개의 비동기 처리를 복잡하지 않은 방법으로 작성하는 것을 알아보았습니다.&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;그러나, Promise는 에러가 어디서 발생했는지 알기 힘들고, 특정 값을 공유하기가 힘들다는 단점을 가집니다. 이에 대해 async / awati을 사용하여 문제점을 해결할 수 있습니다.&lt;/p&gt;</description>
      <category>JavaScript</category>
      <category>JavaScript</category>
      <category>Promise</category>
      <category>비동기처리</category>
      <category>자바스크립트</category>
      <author>oagree0123</author>
      <guid isPermaLink="true">https://oagree0123.tistory.com/12</guid>
      <comments>https://oagree0123.tistory.com/entry/JavaScript-Promise#entry12comment</comments>
      <pubDate>Mon, 6 Sep 2021 11:44:29 +0900</pubDate>
    </item>
  </channel>
</rss>