<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>hmk run dev</title>
    <link>https://hmk1022.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Tue, 19 May 2026 17:05:44 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>hmk run dev</managingEditor>
    <image>
      <title>hmk run dev</title>
      <url>https://tistory1.daumcdn.net/tistory/4630262/attach/f6fb014e901f43039d1cd2a93d824975</url>
      <link>https://hmk1022.tistory.com</link>
    </image>
    <item>
      <title>Cloudflare 터널을 이용한 n8n 접근 설정 가이드</title>
      <link>https://hmk1022.tistory.com/entry/Cloudflare-%ED%84%B0%EB%84%90%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-n8n-%EC%A0%91%EA%B7%BC-%EC%84%A4%EC%A0%95-%EA%B0%80%EC%9D%B4%EB%93%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;안녕하세요! 지난 포스팅에서 도커를 이용한 n8n 셀프호스팅 설정 방법에 대해 알아보았는데요. 이번에는 Cloudflare 터널(Cloudflare Tunnel)을 이용하여 더 안전하고 간편하게 n8n에 접근하는 방법을 알아보겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;목차&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://claude.ai/chat/50eccc5a-08eb-4b31-a55f-ae434af5e2d8#cloudflare-%ED%84%B0%EB%84%90%EC%9D%B4%EB%9E%80&quot;&gt;Cloudflare 터널이란?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://claude.ai/chat/50eccc5a-08eb-4b31-a55f-ae434af5e2d8#cloudflare-%ED%84%B0%EB%84%90%EC%9D%98-%EC%9E%A5%EC%A0%90&quot;&gt;Cloudflare 터널의 장점&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://claude.ai/chat/50eccc5a-08eb-4b31-a55f-ae434af5e2d8#%EC%82%AC%EC%A0%84-%EC%A4%80%EB%B9%84-%EC%82%AC%ED%95%AD&quot;&gt;사전 준비 사항&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://claude.ai/chat/50eccc5a-08eb-4b31-a55f-ae434af5e2d8#cloudflare-%ED%84%B0%EB%84%90-%EC%84%A4%EC%A0%95-%EB%8B%A8%EA%B3%84&quot;&gt;Cloudflare 터널 설정 단계&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://claude.ai/chat/50eccc5a-08eb-4b31-a55f-ae434af5e2d8#%EB%8F%84%EC%BB%A4-%EC%9E%90%EB%8F%99-%EC%8B%A4%ED%96%89-%EC%84%A4%EC%A0%95&quot;&gt;도커 자동 실행 설정&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://claude.ai/chat/50eccc5a-08eb-4b31-a55f-ae434af5e2d8#%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-%EB%B0%8F-%ED%8C%81&quot;&gt;문제 해결 및 팁&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://claude.ai/chat/50eccc5a-08eb-4b31-a55f-ae434af5e2d8#%EB%A7%88%EC%B9%98%EB%A9%B0&quot;&gt;마치며&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1539&quot; data-origin-height=&quot;963&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cifGDC/btsNRS8oSPe/fBzJS59TP3V0wHzKTsYTXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cifGDC/btsNRS8oSPe/fBzJS59TP3V0wHzKTsYTXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cifGDC/btsNRS8oSPe/fBzJS59TP3V0wHzKTsYTXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcifGDC%2FbtsNRS8oSPe%2FfBzJS59TP3V0wHzKTsYTXk%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;1539&quot; height=&quot;963&quot; data-origin-width=&quot;1539&quot; data-origin-height=&quot;963&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Cloudflare 터널이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cloudflare 터널은 공개 IP 주소 없이도 로컬 서버를 인터넷에 안전하게 노출시킬 수 있는 서비스입니다. 기존 방식에서는 방화벽 포트 개방, IP 화이트리스팅, 복잡한 VPN 설정 등이 필요했지만, Cloudflare 터널을 사용하면 이러한 설정 없이도 외부에서 로컬 서버에 접근할 수 있습니다.&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cloudflare 터널은 cloudflared라는 경량 소프트웨어를 사용합니다. 이 소프트웨어는 로컬 머신에서 실행되며, Cloudflare 네트워크와 암호화된 아웃바운드 연결을 만듭니다. 이 연결을 통해 트래픽이 로컬 서비스로 전달됩니다.&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;사용자가 도메인(예: n8n.example.site)에 접속&lt;/li&gt;
&lt;li&gt;Cloudflare 서버가 요청을 수신&lt;/li&gt;
&lt;li&gt;Cloudflare는 cloudflared 클라이언트(터널)를 통해 요청을 로컬 서버에 전달&lt;/li&gt;
&lt;li&gt;로컬 서버가 응답을 다시 터널을 통해 Cloudflare로 보냄&lt;/li&gt;
&lt;li&gt;Cloudflare가 사용자에게 응답 전달&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;Cloudflare 터널의 장점&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;보안 강화&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;외부에서 직접 서버에 접근할 수 없어 DDoS나 직접적인 공격 위험이 감소&lt;/li&gt;
&lt;li&gt;방화벽 포트를 열 필요가 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;간편한 설정&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;무료 SSL/TLS 인증서&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Cloudflare에서 자동으로 SSL/TLS 인증서를 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로컬 개발 환경에서도 사용 가능&lt;/b&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;고정 IP 없이도 사용 가능&lt;/li&gt;
&lt;/ul&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;Cloudflare 터널 vs 단순 포트포워딩: 간단 비교&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Cloudflare 터널의 장점&lt;/h3&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;: 서버 IP가 노출되지 않고, Cloudflare의 보안 기능(DDoS 보호, WAF 등) 활용 가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;설정 편리&lt;/b&gt;: 공유기 설정 변경 불필요, IP 변경에도 영향 없음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자동 SSL&lt;/b&gt;: 인증서 자동 발급 및 갱신&lt;/li&gt;
&lt;li&gt;&lt;b&gt;특수 환경 지원&lt;/b&gt;: CGNAT, 공유 네트워크, 동적 IP 환경에서도 사용 가능&lt;/li&gt;
&lt;li&gt;&lt;b&gt;글로벌 성능&lt;/b&gt;: Cloudflare 네트워크를 통한 속도 개선 가능성&lt;/li&gt;
&lt;/ul&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;b&gt;보안 취약&lt;/b&gt;: 서버 IP와 포트가 직접 노출되어 공격 위험 증가&lt;/li&gt;
&lt;li&gt;&lt;b&gt;관리 번거로움&lt;/b&gt;: 동적 IP 사용 시 지속적 관리 필요&lt;/li&gt;
&lt;li&gt;&lt;b&gt;제한된 환경&lt;/b&gt;: ISP나 공유 네트워크에서 포트포워딩이 막혀있을 수 있음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SSL 설정 필요&lt;/b&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;h2 data-ke-size=&quot;size26&quot;&gt;사전 준비 사항&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Cloudflare 계정&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Cloudflare 계정을 생성하고 도메인을 연결해야 합니다.&lt;/li&gt;
&lt;li&gt;이전 포스팅에서 설명한 &quot;가비아 도메인을 Cloudflare로 연결하기&quot; 부분을 참고하세요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;도커로 실행 중인 n8n&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;n8n이 도커를 통해 로컬에서 실행되고 있어야 합니다.&lt;/li&gt;
&lt;li&gt;기본적으로 포트 5678에서 실행됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;cloudflared 설치&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/installation&quot;&gt;Cloudflare 공식 문서&lt;/a&gt;를 참고하여 OS에 맞게 설치합니다.&lt;/li&gt;
&lt;/ul&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;Cloudflare 터널 설정 단계&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. Cloudflare 로그인 및 인증&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 번째 단계는 cloudflared 클라이언트를 Cloudflare 계정에 연결하는 것입니다. 터미널을 열고 다음 명령어를 실행합니다:&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;cloudflared login
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령어를 실행하면 브라우저가 열리고 Cloudflare 로그인 페이지가 나타납니다. 로그인 후 권한을 부여하면 터널 사용 권한이 cloudflared 클라이언트에 부여됩니다.&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;이제 n8n용 터널을 생성합니다:&lt;/p&gt;
&lt;pre class=&quot;gauss&quot;&gt;&lt;code&gt;cloudflared tunnel create n8n-tunnel
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령어는 n8n-tunnel이라는 이름의 새 터널을 생성합니다. 터널이 생성되면 인증서 파일이 자동으로 ~/.cloudflared 디렉토리에 저장됩니다. 이 인증서는 터널의 고유 ID를 포함하고 있습니다.&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;다음으로, 터널 구성 파일을 생성합니다. 이 파일은 트래픽을 어떻게 라우팅할지 정의합니다:&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;cat &amp;lt;&amp;lt;EOF &amp;gt; ~/.cloudflared/config.yml
tunnel: n8n-tunnel
credentials-file: /Users/example/.cloudflared/2312442-7c232-49f4-852b-12323421.json

ingress:
  - hostname: n8n.example.site     
    service: http://localhost:5678
  - service: http_status:404
EOF&lt;/code&gt;&lt;/pre&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;tunnel: 사용할 터널의 이름&lt;/li&gt;
&lt;li&gt;credentials-file: 터널 인증 파일의 경로 (파일명은 실제 생성된 터널의 ID로 변경해야 합니다)&lt;/li&gt;
&lt;li&gt;ingress: 트래픽 라우팅 규칙
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;hostname: 접속할 도메인 이름&lt;/li&gt;
&lt;li&gt;service: 트래픽을 전달할 로컬 서비스 주소 (n8n이 실행 중인 주소)&lt;/li&gt;
&lt;li&gt;마지막 규칙은 일치하는 규칙이 없을 때 404 에러를 반환합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고&lt;/b&gt;: credentials-file 경로는 본인의 시스템 경로에 맞게 조정해야 합니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. DNS 레코드 생성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터널과 도메인을 연결하기 위해 DNS 레코드를 생성합니다:&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;cloudflared tunnel route dns n8n-tunnel n8n.example.site&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령어는 Cloudflare DNS에 n8n.example.site가 n8n-tunnel을 통해 접근 가능하도록 CNAME 레코드를 자동으로 생성합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. 터널 실행&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 터널을 실행합니다:&lt;/p&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;cloudflared tunnel run n8n-tunnel
&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;이 명령어를 실행하면 터널이 활성화되고, 설정한 도메인(n8n.example.site)을 통해 로컬에서 실행 중인 n8n에 외부에서 접근할 수 있게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터널이 실행되는 동안 로그가 표시되며, CTRL+C를 누르면 터널이 중지됩니다.&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;컴퓨터를 재부팅해도 도커와 n8n이 자동으로 실행되도록 설정하는 방법입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;도커 데스크톱 자동 실행 설정 (Mac/Windows 사용자)&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Docker Desktop 실행&lt;/li&gt;
&lt;li&gt;설정(Settings) 메뉴 열기&lt;/li&gt;
&lt;li&gt;General 탭에서 &quot;Start Docker Desktop when you sign in to your computer&quot; 옵션 체크&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;터널 자동 실행 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아쉽게도 터널은 컴퓨터 재부팅 시 수동으로 다시 실행해야 합니다:&lt;/p&gt;
&lt;pre class=&quot;dockerfile&quot;&gt;&lt;code&gt;cloudflared tunnel run n8n-tunnel
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;리눅스에서 systemd를 이용한 자동 실행 설정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리눅스 서버를 사용하는 경우 systemd 서비스를 생성하여 터널을 자동으로 실행할 수 있습니다:&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;/ol&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;sudo nano /etc/systemd/system/cloudflared.service
&lt;/code&gt;&lt;/pre&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;/ol&gt;
&lt;pre class=&quot;ini&quot;&gt;&lt;code&gt;[Unit]
Description=Cloudflare Tunnel
After=network.target

[Service]
User=&amp;lt;your-username&amp;gt;
ExecStart=/usr/local/bin/cloudflared tunnel run n8n-tunnel
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&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;/ol&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;sudo systemctl enable cloudflared
sudo systemctl start cloudflared
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;macOS에서 launchd를 이용한 자동 실행 설정&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;macOS에서는 launchd를 사용하여 자동 실행을 설정할 수 있습니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;plist 파일 생성:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;nano ~/Library/LaunchAgents/com.cloudflare.tunnel.plist
&lt;/code&gt;&lt;/pre&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;/ol&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;
http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&amp;gt;


    Label
    com.cloudflare.tunnel
    ProgramArguments
    
        /usr/local/bin/cloudflared
        tunnel
        run
        n8n-tunnel
    
    RunAtLoad
    
    KeepAlive
    


&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;plist 파일 로드:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;stylus&quot;&gt;&lt;code&gt;launchctl load ~/Library/LaunchAgents/com.cloudflare.tunnel.plist
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 해결 및 팁&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 터널 연결 문제&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터널 연결에 문제가 있는 경우:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;# 터널 상태 확인
cloudflared tunnel info n8n-tunnel

# 로그 확인
cloudflared tunnel run n8n-tunnel --loglevel debug
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. n8n 설정 조정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n에서 웹훅을 사용할 때는 WEBHOOK_URL 환경 변수를 설정해야 합니다. docker-compose.yml 파일에 다음과 같이 추가합니다:&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;environment:
  - N8N_HOST=n8n.example.site
  - N8N_PROTOCOL=https
  - WEBHOOK_URL=https://n8n.example.site&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 여러 서비스 연결&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 터널로 여러 서비스를 연결할 수 있습니다. config.yml 파일에 여러 서비스를 추가하면 됩니다:&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;ingress:
  - hostname: n8n.example.site
    service: http://localhost:5678
  - hostname: dashboard.example.site
    service: http://localhost:3000
  - service: http_status:404&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cloudflare 터널을 이용하면 복잡한 네트워크 설정 없이도 로컬에서 실행 중인 n8n에 안전하게 접근할 수 있습니다. 특히 개발 환경이나 홈 서버에서 실행 중인 서비스에 접근할 때 유용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방법의 장점은:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;복잡한 포트 포워딩 설정이 필요 없음&lt;/li&gt;
&lt;li&gt;SSL/TLS 자동 설정으로 안전한 접속&lt;/li&gt;
&lt;li&gt;Cloudflare의 보안 기능을 활용할 수 있음&lt;/li&gt;
&lt;li&gt;고정 IP가 없어도 언제든지 접근 가능&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 포스팅에서는 n8n에서 실제 워크플로우를 만들고 자동화하는 방법에 대해 알아보겠습니다. 혹시 질문이나 문제가 있으시면 댓글로 남겨주세요!&lt;/p&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/&quot;&gt;Cloudflare Tunnel 공식 문서&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.n8n.io/hosting/environment-variables/&quot;&gt;n8n 환경 변수 설정 문서&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/cloudflare/cloudflared&quot;&gt;Cloudflared GitHub 저장소&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>AI</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/254</guid>
      <comments>https://hmk1022.tistory.com/entry/Cloudflare-%ED%84%B0%EB%84%90%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-n8n-%EC%A0%91%EA%B7%BC-%EC%84%A4%EC%A0%95-%EA%B0%80%EC%9D%B4%EB%93%9C#entry254comment</comments>
      <pubDate>Sun, 11 May 2025 22:06:56 +0900</pubDate>
    </item>
    <item>
      <title>n8n 무료로 사용하기 (셀프호스팅 도커 환경 구축 - 웹훅 설정부터 도메인 연결까지)</title>
      <link>https://hmk1022.tistory.com/entry/n8n-%EB%AC%B4%EB%A3%8C%EB%A1%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%85%80%ED%94%84%ED%98%B8%EC%8A%A4%ED%8C%85-%EB%8F%84%EC%BB%A4-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95-%EC%9B%B9%ED%9B%85-%EC%84%A4%EC%A0%95%EB%B6%80%ED%84%B0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%97%B0%EA%B2%B0%EA%B9%8C%EC%A7%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근 n8n을 셀프호스팅으로 구축하면서 겪은 경험을 공유하고자 합니다. 이 글에서는 도커를 이용한 n8n 설치부터 웹훅 설정, 그리고 가비아에서 구매한 도메인을 Cloudflare에 연결하는 과정까지 상세하게 설명하겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;목차&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://claude.ai/chat/50eccc5a-08eb-4b31-a55f-ae434af5e2d8#n8n%EC%9D%B4%EB%9E%80&quot;&gt;n8n이란?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://claude.ai/chat/50eccc5a-08eb-4b31-a55f-ae434af5e2d8#%EB%8F%84%EC%BB%A4%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-n8n-%EC%85%80%ED%94%84%ED%98%B8%EC%8A%A4%ED%8C%85-%EA%B5%AC%EC%B6%95&quot;&gt;도커를 이용한 n8n 셀프호스팅 구축&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://claude.ai/chat/50eccc5a-08eb-4b31-a55f-ae434af5e2d8#%EC%9B%B9%ED%9B%85-%EC%84%A4%EC%A0%95%EC%9D%84-%EC%9C%84%ED%95%9C-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%97%B0%EA%B2%B0&quot;&gt;웹훅 설정을 위한 도메인 연결&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://claude.ai/chat/50eccc5a-08eb-4b31-a55f-ae434af5e2d8#%EA%B0%80%EB%B9%84%EC%95%84-%EB%8F%84%EB%A9%94%EC%9D%B8%EC%9D%84-cloudflare%EB%A1%9C-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0&quot;&gt;가비아 도메인을 Cloudflare로 연결하기&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://claude.ai/chat/50eccc5a-08eb-4b31-a55f-ae434af5e2d8#%EB%A7%88%EC%B9%98%EB%A9%B0&quot;&gt;마치며&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;br /&gt;n8n이란?&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2032&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gn9Mr/btsNS56ygbr/jMOVlOF2A3spvwtpX2BWyK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gn9Mr/btsNS56ygbr/jMOVlOF2A3spvwtpX2BWyK/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gn9Mr/btsNS56ygbr/jMOVlOF2A3spvwtpX2BWyK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGn9Mr%2FbtsNS56ygbr%2FjMOVlOF2A3spvwtpX2BWyK%2Fimg.webp&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;687&quot; height=&quot;346&quot; data-origin-width=&quot;2032&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n(노드이트노드)은 워크플로우 자동화 도구로, Zapier나 IFTTT와 같은 서비스와 유사하지만 오픈소스이며 셀프호스팅이 가능합니다. API 연동, 데이터 처리, 자동화 작업 등을 노드 기반 인터페이스를 통해 쉽게 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;br /&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;/li&gt;
&lt;li&gt;200개 이상의 서비스와 연동 가능&lt;/li&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;h2 data-ke-size=&quot;size26&quot;&gt;도커를 이용한 n8n 셀프호스팅 구축&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;도커(Docker)란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도커는 애플리케이션을 컨테이너라는 독립된 환경에서 실행할 수 있게 해주는 플랫폼입니다. 컨테이너는 필요한 모든 종속성과 라이브러리를 포함하고 있어, 어떤 환경에서든 동일하게 작동합니다. 이는 &quot;내 컴퓨터에서는 작동하는데...&quot;라는 문제를 해결해줍니다.&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;n8n 도커 설치 과정&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;도커 설치하기&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 서버에 도커와 도커 컴포즈가 설치되어 있어야 합니다. 리눅스 환경에서는 다음 명령어로 설치할 수 있습니다:&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;# 도커 설치
sudo apt update
sudo apt install docker.io

# 도커 컴포즈 설치
sudo apt install docker-compose

# 도커 서비스 시작 및 자동 시작 설정
sudo systemctl start docker
sudo systemctl enable docker
&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;docker-compose.yml 파일 생성&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 디렉토리를 만들고 그 안에 docker-compose.yml 파일을 생성합니다:&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;mkdir n8n-project
cd n8n-project
touch docker-compose.yml
&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;다음은 기본적인 n8n 구성을 위한 docker-compose.yml 파일 내용입니다:&lt;/p&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;version: '3'

services:
  n8n:
    image: n8nio/n8n
    restart: always
    ports:
      - &quot;5678:5678&quot;
    environment:
      - N8N_HOST=도메인주소 # 여러분의 도메인으로 변경해주세요
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - NODE_ENV=production
      - WEBHOOK_URL=https://도메인주소 # 여러분의 도메인으로 변경해주세요
    volumes:
      - ./n8n_data:/home/node/.n8n
&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;&lt;b&gt;n8n 실행하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker-compose.yml 파일이 있는 디렉토리에서 다음 명령어를 실행합니다:&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;sudo docker-compose up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-d 옵션은 백그라운드에서 실행하도록 합니다. 이제 n8n이 도커 컨테이너 내에서 실행되고 있습니다.&lt;/p&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;실행 중인 n8n의 로그를 확인하려면:&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;sudo docker-compose logs -f n8n
&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;웹훅 설정을 위한 도메인 연결&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;웹훅(Webhook)이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹훅은 특정 이벤트가 발생했을 때 실시간으로 알림을 받을 수 있는 HTTP 콜백 메커니즘입니다. 쉽게 말해, 어떤 서비스에서 이벤트(예: 새 이메일 수신, 결제 완료, GitHub 커밋 등)가 발생하면 미리 지정한 URL로 HTTP 요청을 보내주는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n에서 웹훅은 외부 서비스로부터 트리거를 받아 워크플로우를 실행하기 위한 핵심 기능입니다.&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n에서 웹훅을 사용하기 위해서는 외부에서 접근 가능한 도메인이 필요합니다. 개발 환경에서는 ngrok 같은 터널링 서비스를 사용할 수 있지만, 프로덕션 환경에서는 실제 도메인을 사용하는 것이 좋습니다.&lt;/p&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;도메인을 서버의 IP 주소에 연결해야 합니다. DNS 관리 페이지에서 A 레코드를 생성하여 도메인이 서버 IP를 가리키도록 설정합니다.&lt;/p&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;SSL 인증서 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹훅은 보안을 위해 HTTPS를 사용하는 것이 좋습니다. Let's Encrypt를 이용해 무료 SSL 인증서를 발급받을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 Nginx와 Let's Encrypt를 이용한 설정 예시입니다:&lt;/p&gt;
&lt;pre class=&quot;properties&quot;&gt;&lt;code&gt;# Nginx 설치
sudo apt install nginx

# Certbot 설치 (Let's Encrypt 클라이언트)
sudo apt install certbot python3-certbot-nginx

# SSL 인증서 발급
sudo certbot --nginx -d 여러분의도메인.com
&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;&lt;b&gt;Nginx 리버스 프록시 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n은 기본적으로 5678 포트에서 실행되므로, Nginx를 통해 80/443 포트의 요청을 n8n으로 전달하도록 리버스 프록시를 설정합니다:&lt;/p&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;server {
    listen 80;
    server_name 여러분의도메인.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name 여러분의도메인.com;

    ssl_certificate /etc/letsencrypt/live/여러분의도메인.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/여러분의도메인.com/privkey.pem;

    location / {
        proxy_pass http://localhost:5678;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
&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;Nginx 설정을 저장하고 적용합니다:&lt;/p&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;sudo nginx -t  # 설정 문법 검사
sudo systemctl reload nginx  # 설정 적용
&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;가비아 도메인을 Cloudflare로 연결하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;네임서버(Name Server)란?&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;262&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p4O3w/btsNSnti6CO/BTVxj7RPhAfRboGLqAw5iK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p4O3w/btsNSnti6CO/BTVxj7RPhAfRboGLqAw5iK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p4O3w/btsNSnti6CO/BTVxj7RPhAfRboGLqAw5iK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp4O3w%2FbtsNSnti6CO%2FBTVxj7RPhAfRboGLqAw5iK%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;1024&quot; height=&quot;262&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;262&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;네임서버는 도메인 이름을 IP 주소로 변환해주는 DNS(Domain Name System)의 일부입니다. 쉽게 말해, 우리가 웹브라우저에 도메인 이름을 입력했을 때 해당 웹사이트의 서버를 찾을 수 있도록 도와주는 '전화번호부' 같은 역할을 합니다.&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;Cloudflare란?&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;715&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Rn16i/btsNS2Pwkw0/r8KWoTD3eUzahjtP2xTRS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Rn16i/btsNS2Pwkw0/r8KWoTD3eUzahjtP2xTRS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Rn16i/btsNS2Pwkw0/r8KWoTD3eUzahjtP2xTRS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRn16i%2FbtsNS2Pwkw0%2Fr8KWoTD3eUzahjtP2xTRS0%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;659&quot; height=&quot;368&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;715&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cloudflare는 CDN(Content Delivery Network), DNS 관리, DDoS 방어, SSL 인증서 등 다양한 웹 서비스를 제공하는 회사입니다. 무료 플랜에서도 강력한 기능을 제공하여 많은 개발자들이 사용하고 있습니다.&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;가비아 도메인을 Cloudflare로 이전하는 과정&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;b&gt;Cloudflare 계정 생성 및 도메인 추가&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 &lt;a href=&quot;https://www.cloudflare.com/&quot;&gt;Cloudflare 웹사이트&lt;/a&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;1. DNS 레코드 확인&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cloudflare가 현재 도메인의 DNS 레코드를 스캔합니다. 스캔이 완료되면 결과를 확인하고 필요한 경우 DNS 레코드를 수정합니다.&lt;/p&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;2. 플랜 선택&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cloudflare는 다양한 플랜을 제공하지만, 개인 프로젝트라면 무료 플랜으로도 충분합니다. 필요한 플랜을 선택합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 네임서버 변경&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cloudflare는 여러분의 도메인에 사용할 네임서버 정보를 제공합니다. 일반적으로 다음과 같은 형태입니다:&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;ns1.cloudflare.com
ns2.cloudflare.com
&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;&lt;b&gt;1. 가비아에서 네임서버 변경하기&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;a href=&quot;https://customer.gabia.com/manual/domain/286/991&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;가이드&lt;/a&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;2. 변경 확인 및 적용 대기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네임서버 변경은 전 세계 DNS에 전파되는 데 시간이 걸립니다. 일반적으로 몇 시간에서 최대 48시간까지 소요될 수 있습니다. Cloudflare 대시보드에서 '활성화 확인 중' 상태를 볼 수 있으며, 활성화가 완료되면 '활성화됨' 상태로 변경됩니다.&lt;/p&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;3. SSL/TLS 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Cloudflare 대시보드에서 'SSL/TLS' 메뉴로 이동하여 암호화 모드를 설정합니다. 일반적으로 '유연한' 또는 '전체' 모드를 선택합니다.&lt;/p&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;4. 페이지 규칙 및 추가 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요에 따라 페이지 규칙, 캐시 설정, 방화벽 등 Cloudflare의 다양한 기능을 설정할 수 있습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 n8n을 도커로 셀프호스팅하고, 웹훅을 위한 도메인 설정까지 완료했습니다. 가비아에서 구매한 도메인을 Cloudflare로 연결하여 추가적인 보안과 성능 혜택도 얻었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;n8n을 통해 다양한 서비스를 연동하고 자동화 워크플로우를 구축할 수 있습니다. GitHub, Slack, Google Sheets, 이메일 서비스 등 수많은 서비스와 연동할 수 있으니, 여러분의 업무를 더욱 효율적으로 만들어보세요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적인 질문이나 문제가 있다면 댓글로 남겨주세요. 다음에는 n8n에서 실제 워크플로우를 구축하는 방법에 대해 더 자세히 다루어보겠습니다.&lt;/p&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.n8n.io/&quot;&gt;n8n 공식 문서&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.docker.com/&quot;&gt;Docker 공식 문서&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://support.cloudflare.com/&quot;&gt;Cloudflare 도움말 센터&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/253</guid>
      <comments>https://hmk1022.tistory.com/entry/n8n-%EB%AC%B4%EB%A3%8C%EB%A1%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-%EC%85%80%ED%94%84%ED%98%B8%EC%8A%A4%ED%8C%85-%EB%8F%84%EC%BB%A4-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%B6%95-%EC%9B%B9%ED%9B%85-%EC%84%A4%EC%A0%95%EB%B6%80%ED%84%B0-%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%97%B0%EA%B2%B0%EA%B9%8C%EC%A7%80#entry253comment</comments>
      <pubDate>Sun, 11 May 2025 17:40:19 +0900</pubDate>
    </item>
    <item>
      <title>CI 린트 체크시간 최적화하기</title>
      <link>https://hmk1022.tistory.com/entry/CI-%EB%A6%B0%ED%8A%B8-%EC%B2%B4%ED%81%AC%EC%8B%9C%EA%B0%84-%EC%B5%9C%EC%A0%81%ED%99%94%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;모노레포에서 린트 작업의 처리 속도를 크게 향상시키기 위해, 동기 방식에서 비동기 방식으로 전환한 경험을 공유합니다. Node.js의 이벤트 루프와 비동기 처리의 원리를 이해하면 빌드 파이프라인의 효율성을 대폭 개선할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDr8ZX/btsNQ2ayw4B/kL47ZeiSSKh9rP4plen1xk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDr8ZX/btsNQ2ayw4B/kL47ZeiSSKh9rP4plen1xk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDr8ZX/btsNQ2ayw4B/kL47ZeiSSKh9rP4plen1xk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDr8ZX%2FbtsNQ2ayw4B%2FkL47ZeiSSKh9rP4plen1xk%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;364&quot; height=&quot;310&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;310&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모노레포 프로젝트가 커질수록 린트 작업은 점점 더 많은 시간을 소요합니다. 특히 CI/CD 파이프라인에서 모든 패키지를 일일이 검사하는 과정은 개발 생산성을 저하시키는 주요 요인이 됩니다. 기존에는 변경된 패키지마다 린트 작업을 순차적으로(동기적으로) 실행했으나, 이 방식은 패키지 수가 늘어날수록 선형적으로 시간이 증가하는 문제가 있었습니다.&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;코드를 분석해보면, 기존에는 execSync를 사용해 패키지별 린트 작업을 순차적으로 처리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 exec와 Promise를 활용한 비동기 병렬 처리 방식으로 변경하여 린트 시간을 획기적으로 단축했습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;execSync와 exec의 차이&lt;/h2&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;execSync - 동기적 실행&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1746717550710&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { execSync } = require('child_process');

// 이전 코드(가정)
affectedPackages.forEach((pkgPath) =&amp;gt; {
  console.log(`Starting lint for ${pkgPath}...`);
  try {
    const output = execSync(`pnpm turbo lint --filter=./${pkgPath}`, { encoding: 'utf-8' });
    console.log(`Completed lint for ${pkgPath}`);
    console.log(output);
  } catch (error) {
    console.error(`Error in ${pkgPath}:`, error.stderr);
    process.exit(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;&lt;br /&gt;execSync는 동기적으로 작동합니다.&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;패키지 A의 린트가 끝나야만 패키지 B의 린트가 시작됩니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;exec - 비동기적 실행&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1746717579230&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { exec } = require('child_process');

// 새 코드
const promises = packagesArray.map((pkgPath) =&amp;gt; {
  return new Promise((resolve, reject) =&amp;gt; {
    console.log(`Starting lint for ${pkgPath}...`);
    exec(`pnpm turbo lint --filter=./${pkgPath}`, (error, stdout, stderr) =&amp;gt; {
      if (error) {
        console.error(`Error in ${pkgPath}:`, stderr);
        reject(error);
        return;
      }
      console.log(`Completed lint for ${pkgPath}`);
      console.log(stdout);
      resolve();
    });
  });
});

Promise.all(promises).catch((_) =&amp;gt; {
  process.exit(1);
});&lt;/code&gt;&lt;/pre&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;1280&quot; data-origin-height=&quot;1014&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boT9pS/btsNPaauiMk/k4NNkovxMKz7AVsX8nJ82K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boT9pS/btsNPaauiMk/k4NNkovxMKz7AVsX8nJ82K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boT9pS/btsNPaauiMk/k4NNkovxMKz7AVsX8nJ82K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboT9pS%2FbtsNPaauiMk%2Fk4NNkovxMKz7AVsX8nJ82K%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;1280&quot; height=&quot;1014&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1014&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;exec는 비동기적으로 작동합니다:&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;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;Node.js 이벤트 루프와 비동기 처리 이해하기&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이벤트 루프란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.js의 핵심은 단일 스레드 기반의 이벤트 루프입니다. 이는 자바스크립트가 비동기 작업을 처리하는 방식의 기본 메커니즘입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;동기 vs 비동기 &amp;amp; 블록 vs 논블록&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;블록 + 동기 (execSync 방식)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;작업 A가 완료될 때까지 다음 작업이 시작되지 않습니다.&lt;/li&gt;
&lt;li&gt;한 번에 하나의 작업만 처리됩니다.&lt;/li&gt;
&lt;li&gt;자원 활용이 비효율적입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;논블록 + 비동기 (exec + Promise 방식)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;작업 A를 시작한 후 완료를 기다리지 않고 작업 B, C를 진행합니다.&lt;/li&gt;
&lt;li&gt;작업이 완료되면 콜백(Promise의 resolve)을 통해 결과를 처리합니다.&lt;/li&gt;
&lt;li&gt;여러 작업이 병렬로 처리되어 CPU와 I/O 자원을 효율적으로 활용합니다.&lt;/li&gt;
&lt;/ul&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;h3 data-ke-size=&quot;size23&quot;&gt;동작 원리&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;각 패키지마다 린트 명령을 비동기적으로 실행하는 Promise 객체를 생성합니다.&lt;/li&gt;
&lt;li&gt;Promise.all을 사용해 모든 린트 작업이 병렬로 실행되게 합니다.&lt;/li&gt;
&lt;li&gt;어느 하나라도 실패하면 전체 프로세스가 실패로 간주됩니다.&lt;/li&gt;
&lt;/ol&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;패키지 수execSync (순차 처리)exec + Promise (병렬 처리)개선율&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;5개&lt;/td&gt;
&lt;td&gt;약 50초&lt;/td&gt;
&lt;td&gt;약 15초&lt;/td&gt;
&lt;td&gt;70%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10개&lt;/td&gt;
&lt;td&gt;약 100초&lt;/td&gt;
&lt;td&gt;약 20초&lt;/td&gt;
&lt;td&gt;80%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20개&lt;/td&gt;
&lt;td&gt;약 200초&lt;/td&gt;
&lt;td&gt;약 25초&lt;/td&gt;
&lt;td&gt;87.5%&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;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;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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;자원 사용량&lt;/b&gt;: 병렬 처리는 CPU와 메모리 사용량이 증가할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;의존성 문제&lt;/b&gt;: 패키지 간 의존성이 있는 경우 병렬 처리가 문제를 일으킬 수 있습니다(이 경우 Turborepo의 의존성 관리 기능이 도움이 됩니다).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;동시성 제한&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;브라우저 vs Node.js 비동기 처리 비교&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;libuv는 내부적으로 &lt;b&gt;스레드 풀&lt;/b&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;브라우저 내장 API + 운영체제&lt;/td&gt;
&lt;td&gt;libuv 라이브러리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;병렬 처리 방식&lt;/td&gt;
&lt;td&gt;브라우저 내부 스레드 + 운영체제 API&lt;/td&gt;
&lt;td&gt;libuv 스레드 풀 + 운영체제 API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;파일 시스템 액세스&lt;/td&gt;
&lt;td&gt;제한적 (File API)&lt;/td&gt;
&lt;td&gt;전체 접근 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;네트워크 요청&lt;/td&gt;
&lt;td&gt;Fetch API, XMLHttpRequest&lt;/td&gt;
&lt;td&gt;http, https, net 모듈&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;병렬 JavaScript 실행&lt;/td&gt;
&lt;td&gt;Web Workers&lt;/td&gt;
&lt;td&gt;Worker Threads&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;프로세스 생성&lt;/td&gt;
&lt;td&gt;불가능&lt;/td&gt;
&lt;td&gt;child_process 모듈&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&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;더 나아가 다음과 같은 방법으로 성능을 추가 개선할 수 있습니다:&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;동시성 제한 도입&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #383a42; text-align: left;&quot;&gt;&lt;code&gt;// p-limit 라이브러리 활용 예시
const pLimit = require('p-limit');
const limit = pLimit(4); // 최대 4개 작업만 동시에 실행

const promises = packagesArray.map((pkgPath) =&amp;gt; {
  return limit(() =&amp;gt; new Promise((resolve, reject) =&amp;gt; {
    // exec 비동기 호출
  }));
});&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;: Turborepo의 캐싱 기능을 최대한 활용하여 중복 작업을 방지합니다.&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;Node.js에서 execSync에서 exec로의 전환은 단순한 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;이러한 변경을 통해 린트 시간을 크게 단축할 수 있었고, 개발자 경험과 CI/CD 파이프라인의 효율성을 모두 향상시킬 수 있었습니다. 모노레포 환경에서 빌드 파이프라인을 최적화할 때는 항상 비동기 처리와 병렬화를 고려해보시기 바랍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비동기 처리는 JavaScript의 강력한 특징 중 하나이며, 이를 효과적으로 활용하면 성능 개선의 큰 열쇠가 됩니다!&lt;/p&gt;</description>
      <category>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/252</guid>
      <comments>https://hmk1022.tistory.com/entry/CI-%EB%A6%B0%ED%8A%B8-%EC%B2%B4%ED%81%AC%EC%8B%9C%EA%B0%84-%EC%B5%9C%EC%A0%81%ED%99%94%ED%95%98%EA%B8%B0#entry252comment</comments>
      <pubDate>Fri, 9 May 2025 00:31:00 +0900</pubDate>
    </item>
    <item>
      <title>블록과 논블록, 동기와 비동기</title>
      <link>https://hmk1022.tistory.com/entry/%EB%B8%94%EB%A1%9D%EA%B3%BC-%EB%85%BC%EB%B8%94%EB%A1%9D-%EB%8F%99%EA%B8%B0%EC%99%80-%EB%B9%84%EB%8F%99%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;오늘은 프로그래밍에서 매우 중요한 개념인 블록(Block)과 논블록(Non-block), 그리고 동기(Synchronous)와 비동기(Asynchronous) 처리에 대해 자세히 알아보겠습니다. 이 개념들은 종종 혼동되기 쉽지만, 효율적인 프로그래밍을 위해 반드시 이해해야 하는 핵심 요소입니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1201&quot; data-origin-height=&quot;980&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cwpAAE/btsNJZ7WSdE/nalvYO9ri6CkKqhIkSMEg1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cwpAAE/btsNJZ7WSdE/nalvYO9ri6CkKqhIkSMEg1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cwpAAE/btsNJZ7WSdE/nalvYO9ri6CkKqhIkSMEg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcwpAAE%2FbtsNJZ7WSdE%2FnalvYO9ri6CkKqhIkSMEg1%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;794&quot; height=&quot;648&quot; data-origin-width=&quot;1201&quot; data-origin-height=&quot;980&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;블록 vs 논블록&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;b&gt;블록(Block)&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;특정 작업이 완료될 때까지 다음 작업으로 진행하지 않고 대기하는 방식&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;프로그램이 해당 작업에 &quot;차단(blocked)&quot;되어 있는 상태&lt;/li&gt;
&lt;li&gt;작업이 끝날 때까지 제어권을 돌려받지 못함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;논블록(Non-block)&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;작업 완료 여부와 상관없이 다음 작업으로 즉시 진행하는 방식&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;프로그램이 &quot;차단되지 않고(non-blocked)&quot; 계속 실행됨&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;동기 vs 비동기&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동기(Synchronous)&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;작업이 순차적으로 실행&lt;/b&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;&lt;b&gt;비동기(Asynchronous)&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;기다리지 않고 다음 작업을 진행&lt;/b&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;블록/논블록과 동기/비동기의 관계&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두 쌍의 개념은 서로 다른 측면을 다루고 있습니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;블록/논블록&lt;/b&gt;은 제어권(control flow)에 관한 것&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;따라서 이론적으로는 다음과 같은 조합이 가능합니다:&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;블록 + 동기&lt;/b&gt;: 가장 전통적인 방식 (예: 일반적인 함수 호출)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;논블록 + 비동기&lt;/b&gt;: 현대적 웹 개발에서 많이 사용 (예: AJAX 요청)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;블록 + 비동기&lt;/b&gt;: 드물게 사용 (예: 일부 멀티스레딩 상황)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;논블록 + 동기&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;장단점 비교&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;블록 처리의 장단점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&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;/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;&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;자원 활용 효율이 낮음 (대기 시간 동안 CPU 유휴 상태)&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;논블록 처리의 장단점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&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;/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;&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;/li&gt;
&lt;li&gt;디버깅이 어려움&lt;/li&gt;
&lt;li&gt;경쟁 상태(race condition)와 같은 동시성 문제 발생 가능&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&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;/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;&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;I/O 작업 등에서 효율이 낮음&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;비동기 처리의 장단점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&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;/li&gt;
&lt;li&gt;병렬 처리 가능&lt;/li&gt;
&lt;li&gt;I/O 바운드 작업에 이상적&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&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;콜백 지옥(callback hell)과 같은 코드 복잡성&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;h2 data-ke-size=&quot;size26&quot;&gt;실전 적용 가이드&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;블록 처리를 사용해야 할 때&lt;/h3&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;초기화 과정과 같이 반드시 순차적으로 실행되어야 하는 경우&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;논블록 처리를 사용해야 할 때&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;UI 응답성이 중요한 클라이언트 애플리케이션&lt;/li&gt;
&lt;li&gt;네트워크 통신이나 파일 I/O와 같이 대기 시간이 긴 작업&lt;/li&gt;
&lt;li&gt;동시에 여러 작업을 처리해야 하는 서버&lt;/li&gt;
&lt;li&gt;실시간 데이터 처리가 필요한 경우&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;동기 처리를 사용해야 할 때&lt;/h3&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;작업의 결과가 즉시 필요한 경우&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;비동기 처리를 사용해야 할 때&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;네트워크 요청, 데이터베이스 쿼리 등 I/O 바운드 작업&lt;/li&gt;
&lt;li&gt;대용량 데이터 처리&lt;/li&gt;
&lt;li&gt;사용자 인터페이스의 응답성 유지가 중요한 경우&lt;/li&gt;
&lt;li&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;프로그래밍 언어별 구현 사례&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;JavaScript&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript는 단일 스레드 언어지만 비동기 처리를 위한 다양한 메커니즘을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1746521048252&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 블록 + 동기
function syncBlock() {
  const result = expensiveCalculation(); // 이 함수가 완료될 때까지 대기
  console.log(result);
}

// 논블록 + 비동기 (콜백 방식)
function asyncNonBlock() {
  fetchData((result) =&amp;gt; {
    console.log(result);
  });
  console.log(&quot;요청 시작됨&quot;); // fetchData 완료 전에 실행됨
}

// 논블록 + 비동기 (Promise 방식)
function asyncNonBlockPromise() {
  fetchDataPromise()
    .then(result =&amp;gt; console.log(result))
    .catch(error =&amp;gt; console.error(error));
  console.log(&quot;요청 시작됨&quot;); // Promise 완료 전에 실행됨
}

// 논블록 + 비동기 (async/await 방식 - 문법적으로는 동기식처럼 보이지만 내부적으로는 비동기)
async function asyncNonBlockAwait() {
  console.log(&quot;요청 시작됨&quot;);
  try {
    const result = await fetchDataPromise(); // 비동기지만 코드는 동기식처럼 보임
    console.log(result);
  } catch (error) {
    console.error(error);
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;h3 data-ke-size=&quot;size23&quot;&gt;웹 개발에서의 API 호출&lt;/h3&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;b&gt;블록 + 동기 방식&lt;/b&gt;:&lt;/p&gt;
&lt;pre id=&quot;code_1746521074507&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 블록 + 동기 (권장하지 않음)
function getDataSync() {
  const xhr = new XMLHttpRequest();
  xhr.open('GET', 'https://api.example.com/data', false); // 동기 모드
  xhr.send();
  if (xhr.status === 200) {
    return JSON.parse(xhr.responseText);
  }
}
// 주의: 이 방식은 브라우저 메인 스레드를 차단하여 UI 응답성을 저하시킴&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;&lt;b&gt;논블록 + 비동기 방식 (권장)&lt;/b&gt;:&lt;/p&gt;
&lt;pre id=&quot;code_1746521099081&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 논블록 + 비동기 (fetch API)
function getDataAsync() {
  fetch('https://api.example.com/data')
    .then(response =&amp;gt; response.json())
    .then(data =&amp;gt; {
      updateUI(data); // 데이터가 준비되면 UI 업데이트
    })
    .catch(error =&amp;gt; console.error('Error:', error));
  
  showLoadingIndicator(); // 즉시 실행되어 사용자에게 로딩 중임을 표시
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;[Q&amp;amp;A] async/await는 블록인가 논블록인가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Q: API 호출에 await를 사용하면 응답을 기다려야 하므로 블록 방식이 아닌가요?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A:&lt;/b&gt; 이 질문은 매우 좋은 포인트를 짚고 있습니다! async/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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;함수 내부 관점:&lt;/b&gt; await는 해당 함수 내에서 Promise가 해결될 때까지 다음 코드 실행을 일시 중지합니다. 이런 면에서는 &quot;블록&quot;처럼 보입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1746521694347&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;async function getData() {
  console.log(&quot;1. 요청 전&quot;);
  const data = await fetchAPI(); // 여기서 함수 실행이 일시 중지됨
  console.log(&quot;3. 데이터 수신 후&quot;); // 응답이 올 때까지 실행되지 않음
  return data;
}&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;b&gt;전체 프로그램 관점:&lt;/b&gt; await를 만나면 함수 실행은 일시 중지되지만, 중요한 점은 &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_1746521713210&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;getData();
console.log(&quot;2. getData 호출 후 즉시 실행&quot;); // 데이터를 기다리지 않고 실행됨

// 실행 순서: 1 &amp;rarr; 2 &amp;rarr; 3&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;이처럼 async/await는 개발자에게는 동기 코드처럼 보이는 가독성을 제공하면서도, 실제로는 프로그램 전체가 블록되지 않는 논블록 방식으로 동작합니다. 이것이 JavaScript의 비동기 프로그래밍의 강력한 특징입니다.&lt;/p&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 호출을 await로 처리하는 코드는 전체 시스템 관점에서 볼 때 &quot;논블록 + 비동기&quot; 패턴이라고 할 수 있습니다!&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;p data-ke-size=&quot;size16&quot;&gt;Node.js에서 파일 시스템 작업 시:&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_1746521120728&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;javascript// 블록 + 동기
const fs = require('fs');

function readFileSync() {
  try {
    const data = fs.readFileSync('large-file.txt', 'utf8');
    console.log(data);
  } catch (error) {
    console.error('Error:', error);
  }
  console.log('파일 읽기 완료'); // 파일 읽기가 완료된 후에만 실행됨
}&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;b&gt;논블록 + 비동기 방식&lt;/b&gt;:&lt;/p&gt;
&lt;pre id=&quot;code_1746521139522&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 논블록 + 비동기
const fs = require('fs');

function readFileAsync() {
  fs.readFile('large-file.txt', 'utf8', (error, data) =&amp;gt; {
    if (error) {
      console.error('Error:', error);
      return;
    }
    console.log(data);
  });
  console.log('파일 읽기 요청됨'); // 파일 읽기 완료 전에 실행됨
}&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.js와 MongoDB를 사용한 데이터베이스 쿼리:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;블록 + 동기 방식 (잘 사용하지 않음)&lt;/b&gt;:&lt;/p&gt;
&lt;pre id=&quot;code_1746521164231&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 블록 + 동기 (가상의 예시, 실제로는 권장하지 않음)
function findUserSync(id) {
  const user = db.collection('users').findOneSync({ _id: id });
  return user;
}&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;&lt;b&gt;논블록 + 비동기 방식 (권장)&lt;/b&gt;:&lt;/p&gt;
&lt;pre id=&quot;code_1746521180204&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 논블록 + 비동기 (Promise)
function findUserAsync(id) {
  return db.collection('users').findOne({ _id: id })
    .then(user =&amp;gt; {
      return processUser(user);
    })
    .catch(error =&amp;gt; {
      console.error('Error:', error);
      throw error;
    });
}

// 논블록 + 비동기 (async/await)
async function findUserAsyncAwait(id) {
  try {
    const user = await db.collection('users').findOne({ _id: id });
    return processUser(user);
  } catch (error) {
    console.error('Error:', error);
    throw error;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;최근 프로그래밍 패러다임은 비동기 논블록 처리 쪽으로 크게 기울고 있습니다:&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;리액티브 프로그래밍&lt;/b&gt;: 데이터 스트림과 변화 전파를 중심으로 한 비동기 프로그래밍 패러다임 (예: RxJS, ReactiveX)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이벤트 기반 아키텍처&lt;/b&gt;: 이벤트 생성과 소비를 통한 느슨한 결합의 시스템 구축 (예: Node.js의 이벤트 루프)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서버리스 컴퓨팅&lt;/b&gt;: 비동기 처리에 최적화된 클라우드 서비스 (예: AWS Lambda)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;마이크로서비스 아키텍처&lt;/b&gt;: 독립적으로 배포 가능한 서비스들의 비동기 통신&lt;/li&gt;
&lt;/ol&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;/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;작업의 특성 파악&lt;/b&gt;: I/O 바운드인지, CPU 바운드인지 분석&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사용자 경험 고려&lt;/b&gt;: 응답성이 중요한지, 처리 속도가 중요한지 판단&lt;/li&gt;
&lt;li&gt;&lt;b&gt;개발 복잡성 평가&lt;/b&gt;: 팀의 역량과 프로젝트 요구사항에 맞는 방식 선택&lt;/li&gt;
&lt;li&gt;&lt;b&gt;최신 API와 라이브러리 활용&lt;/b&gt;: 각 언어와 플랫폼에서 제공하는 최적화된 도구 사용&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 개념을 제대로 이해하고 적용한다면, 더 효율적이고 반응성 높은 애플리케이션을 개발할 수 있을 것입니다.&lt;/p&gt;</description>
      <category>programming</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/251</guid>
      <comments>https://hmk1022.tistory.com/entry/%EB%B8%94%EB%A1%9D%EA%B3%BC-%EB%85%BC%EB%B8%94%EB%A1%9D-%EB%8F%99%EA%B8%B0%EC%99%80-%EB%B9%84%EB%8F%99%EA%B8%B0#entry251comment</comments>
      <pubDate>Tue, 6 May 2025 17:57:46 +0900</pubDate>
    </item>
    <item>
      <title>셀프회고(2025.05.05)</title>
      <link>https://hmk1022.tistory.com/entry/%EC%85%80%ED%94%84%ED%9A%8C%EA%B3%A020250505</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이직 후 6개월이 넘는 시간 동안, 저는 통신 도메인 회사의 PMF(Product Market Fit)를 찾는 팀에 소속되어 있습니다. 아직 큰 성과를 내지 못했지만, 30조 시장에서 아무도 도전하지 않았던 통신 시장의 문제를 해결한다는 설렘을 가지고 계속해서 목표를 향해 나아가고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;100% 확신을 갖기는 어렵지만, 언젠가 모요가 통신시장의 문제를 해결하고 PMF를 찾을 것이라는 믿음을 가지고 일하는 중 입니다~!&lt;br /&gt;&lt;br /&gt;이 확신은 제가 직접 경험한 불편함, 필드리서치, 사용자 테스트, 그리고 주변 사람들이 겪고 있는 명확한 문제들에 기반합니다. 특히 이러한 불편함을 해결하고자 하는 플레이어가 저희가 유일하다는 점(&lt;s&gt;물론 비판적 시각에서 지금까지 이 문제가 해결되지 않은 이유가 있을 수도 있다는 생각도 합니다.&lt;/s&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;(작은 위안으로, Canva, Notion, Figma와 같은 성공적인 기업들도 PMF 달성에 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;팀원 각자가 직군에 상관없이 메이커로서의 모습을 보여주어 큰 동기부여가 되었습니다. 거의 모든 구성원이 오너십을 가지고 프로페셔널한 태도로 적극적으로 도전하는 모습에 저 역시 그 분위기에 깊이 빠져들어 제품만 생각하며 생활하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트엔드 개발자로 시작했지만, 이제는 필드리서치, 사용자 테스트 등을 거치며 길가다 휴대폰을 사용하는 사람들에게 자연스럽게 말을 걸 수 있는 &quot;철판&quot;까지 장착하게 되었죠 ㅎㅎ&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;587&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FZEaA/btsNLamWj6G/KWkFBp3Iegjaij9STn9sE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FZEaA/btsNLamWj6G/KWkFBp3Iegjaij9STn9sE1/img.png&quot; data-alt=&quot;우리팀 (tmi - 쌍수한 디자이너와 호칭에 맞게. 뒷 모습만 보이는 백엔드 개발자)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FZEaA/btsNLamWj6G/KWkFBp3Iegjaij9STn9sE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFZEaA%2FbtsNLamWj6G%2FKWkFBp3Iegjaij9STn9sE1%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;544&quot; height=&quot;436&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;587&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;우리팀 (tmi - 쌍수한 디자이너와 호칭에 맞게. 뒷 모습만 보이는 백엔드 개발자)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;제품 성공을 위한 고민&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제품을 위해 헌신하고 밤낮을 가리지 않는 분위기 속에서, &quot;어떤 프론트엔드 개발자 혹은 팀원이 되어야 이 팀이 목표를 이루는 데 일조할 수 있을까?&quot;라는 생각을 많이 하게 되었고 실제 액션했던 것들&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 빠르게 가설을 검증하기 위해 빠르고 안정적인 서비스를 딜리버리 할 수 있는 역량&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;pmf를 찾기위해 다양한 가치나 소구 포인트로 여러 제품을 만들어야하는 상황에서 빠르지만 안정적인 서비스를 만들어야 했어요&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;사실 한정된 자원, 시간 속에서 안정성을 위한 테스트 등을 많이 챙기진 못했지만 중요 로직이나 함수는 테스터블하게 만들고 테스트 코드를 검증하려고 했어요, 그리고 오류를 적시에 발견할 수 있도록 센트리, 데이터독과 같은 로깅 시스템을 적극 활용했어요&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 데이터 기반으로 UI/UX를 검증하고 개선 방향까지 제시 할 수 있는 역량&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;팀에선 믹스패널을 이용해 유저 행동을 수집하고 이를 통해 데이터 기반으로 UI/UX를 개선하는 방식으로 일했어요,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;저는 프론트엔드 개발자이지만, 배포전까지 가장 화면을 많이 보는 사람으로써 개선방향을 적극적으로 제안했고&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; 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;1921&quot; data-origin-height=&quot;391&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMidSx/btsNMeIVpf7/ebKazEs2kcDPHzzVRziDiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMidSx/btsNMeIVpf7/ebKazEs2kcDPHzzVRziDiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMidSx/btsNMeIVpf7/ebKazEs2kcDPHzzVRziDiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMidSx%2FbtsNMeIVpf7%2FebKazEs2kcDPHzzVRziDiK%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;1921&quot; height=&quot;391&quot; data-origin-width=&quot;1921&quot; data-origin-height=&quot;391&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 원팀으로써 헌신하고 주체적으로 팀원의 불편함을 찾아서 개선할 수 있는 사람&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;때로는 프론트엔드 직군이라는 틀에서 벗어나 팀이나 조직의 목표를 위해 헌신하거나, 손이 남는 시점에 동료의 불편함을 개선할 수 있는 사람 같이 일하는 팀원이 되고자 노력했어요 데이터 분석가 동료를 위한 스크래핑 봇, 다수의 인플루언서 컨택을 하고 싶은 마케팅 팀을 위한 인스타 그램 DM 자동화 봇, SKT 유심사태 TF 리소스 지원 등 도움을 줄 수 있는 곳에 원팀으로써 적극적으로 리소스를 지원했어요&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;743&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/B2iGi/btsNLrvhJrA/Z1uH8oKTcuhmYPt6XD5QpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/B2iGi/btsNLrvhJrA/Z1uH8oKTcuhmYPt6XD5QpK/img.png&quot; data-alt=&quot;SKT 유심사태로 인한 당일 tf 결성 후 밤샘작업을 하고 본 일출&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/B2iGi/btsNLrvhJrA/Z1uH8oKTcuhmYPt6XD5QpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FB2iGi%2FbtsNLrvhJrA%2FZ1uH8oKTcuhmYPt6XD5QpK%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;686&quot; height=&quot;492&quot; data-origin-width=&quot;743&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;SKT 유심사태로 인한 당일 tf 결성 후 밤샘작업을 하고 본 일출&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1834&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9fyds/btsNJ6lxrLQ/4VD4CohuZSfturi1dBnoRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9fyds/btsNJ6lxrLQ/4VD4CohuZSfturi1dBnoRk/img.png&quot; data-alt=&quot;동료에 불편함을 해결해주고 받은 첫 shout out!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9fyds/btsNJ6lxrLQ/4VD4CohuZSfturi1dBnoRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9fyds%2FbtsNJ6lxrLQ%2F4VD4CohuZSfturi1dBnoRk%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;1834&quot; height=&quot;556&quot; data-origin-width=&quot;1834&quot; data-origin-height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;동료에 불편함을 해결해주고 받은 첫 shout out!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;물론 이 과정들은 너무 재밌었지만, 프론트엔드 챕터로써 DX를 개선 경험이 적었던 것은 조금 아쉬웠어요 ㅎㅎ&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 부분은 여러 동료들에게 1on1을 하며 상담했지만, 현재로써 pmf를 찾고 스쿼드에 전념하는 것이 좋다고 스스로 판단해서&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;조금 아쉽지만 틈틈히 의식적으로 노력해 채워가야할 부분이 아닌가 스스로 생각이 듭니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;누구도 도전하지 않았던 시장에서 PMF를 찾는 과정은 설레면서도 결코 쉽지 않음을 매 순간 피부로 느끼고 있습니다. 그래서 더욱 이 문제를 해결하고 싶고 헌신하고 싶다는 생각이 듭니다. 여전히 부족한 부분이 많아 스스로와 동료들에게 피드백을 받으며 성장해야겠습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로는 단순히 &quot;무언가 해보자&quot;는 시도보다는, 팀이 집중하는 가설이나 문제의 흐름을 더 깊이 이해하고, 그 속에서 진정으로 필요한 기술적/제품적 인풋을 탐색하겠습니다. 또한, 단순 실행자가 아닌 DRI로서 팀에 임팩트 있는 기여를 제안하고 실현하는 역할을 더 명확히 하겠습니다. 이를 위해 사소하더라도 '무엇을 위해 하는가'를 더 자주 질문하고, 챌린지를 받는 것에도 열린 자세를 유지해야겠습니다!&lt;/p&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;
&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>의도적수련</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/250</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%85%80%ED%94%84%ED%9A%8C%EA%B3%A020250505#entry250comment</comments>
      <pubDate>Tue, 6 May 2025 00:49:55 +0900</pubDate>
    </item>
    <item>
      <title>카카오 로그인 URL 길이 제한 문제와 해결방안</title>
      <link>https://hmk1022.tistory.com/entry/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EB%A1%9C%EA%B7%B8%EC%9D%B8-URL-%EA%B8%B8%EC%9D%B4-%EC%A0%9C%ED%95%9C-%EB%AC%B8%EC%A0%9C%EC%99%80-%ED%95%B4%EA%B2%B0%EB%B0%A9%EC%95%88</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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;472&quot; data-origin-height=&quot;214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvZRGx/btsNKxCTrLf/yAdcpsvdNY588WUlH5UbF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvZRGx/btsNKxCTrLf/yAdcpsvdNY588WUlH5UbF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvZRGx/btsNKxCTrLf/yAdcpsvdNY588WUlH5UbF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvZRGx%2FbtsNKxCTrLf%2FyAdcpsvdNY588WUlH5UbF0%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;472&quot; height=&quot;214&quot; data-origin-width=&quot;472&quot; data-origin-height=&quot;214&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 애플리케이션 개발 중 예상치 못한 에러를 마주칠 때가 있습니다. 그중에서도 특히 외부 API와 연동할 때 발생하는 문제는 디버깅이 어려울 수 있습니다. 최근 저희 팀은 카카오 로그인 구현 과정에서 긴 URL로 인해 발생하는 404 에러와 Nginx 오류 화면을 마주쳤습니다. 이 글에서는 그 원인과 해결 방안, 그리고 이와 관련된 개발 시 고려해야 할 사항들을 공유하고자 합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제 상황&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카카오 로그인 구현 시 kauth.kakao.com/oauth/authorize로 로그인 요청을 보내는 과정에서 URL이 너무 길 경우 404 에러 및 Nginx 오류 화면이 나타나는 문제가 발생했습니다. 특히 UTM 파라미터(마케팅 추적 코드)와 같은 추가 매개변수가 포함된 경우에 이런 현상이 두드러졌습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제의 예시&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 긴 URL로 요청을 보낼 경우 오류가 발생했습니다:&lt;/p&gt;
&lt;pre class=&quot;perl&quot;&gt;&lt;code&gt;https://kauth.kakao.com/oauth/authorize?client_id=97cdc170451dc8b3186cb5853bd0feed&amp;amp;redirect_uri=https%3A%2F%2Fwww.moyoplan.com%2Fr%2Flogin%2Fkakao&amp;amp;response_type=code&amp;amp;state=%7B%22next%22%3A%22%2Fr%2Fmohyo-pickup%2Fsend%3FsellerName%3DLG...
(이하 생략된 매우 긴 URL)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 state 파라미터 내에 포함된 JSON 데이터가 매우 길고, UTM 파라미터(utm_medium, utm_source, utm_campaign 등)와 Facebook 추적 코드(fbclid)가 여러 위치에 중복 포함되어 있었습니다.&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;h3 data-ke-size=&quot;size23&quot;&gt;Nginx의 URL 길이 제한&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제의 주된 원인은 Nginx 웹 서버의 URL 길이 제한에 있었다고 추측했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nginx는 기본적으로 요청 URL에 길이 제한을 두고 있으며, 이 제한을 초과하면 414(Request-URI Too Large) 에러를 반환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Nginx의 URL 길이 제한은 large_client_header_buffers 설정으로 관리됩니다. 기본 설정은 다음과 같습니다:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;large_client_header_buffers 4 8k;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 4개의 버퍼를 사용하며 각 버퍼 크기가 8KB라는 의미입니다. 하지만 요청 라인(HTTP 메서드, URL, 프로토콜 버전)은 한 버퍼 크기를 초과할 수 없으므로, 실제 URL 길이 제한은 약 8KB보다 작습니다. 일반적으로 Nginx는 최대 URL 길이를 약 4KB(4,096 bytes)로 제한하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 414에러 대신 404에러를 뱉었다는 점을 미루어보아&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 414에러 대신 404에러를 뱉었다는 점을 미루어보아, 카카오의 인증 서버에는 표준 HTTP 프로토콜과 다른 커스텀한 에러 처리 로직이 구현되어 있을 가능성이 큽니다. HTTP 표준에 따르면 URL이 너무 길 경우 414(URI Too Long) 에러를 반환하는 것이 적절합니다. 하지만 카카오에서는 이런 상황에 404(Not Found) 에러를 반환했습니다.&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;첫째, 카카오의 인증 서버는 다중 계층 아키텍처로 구성되어 있을 수 있습니다. 외부에서 접근 가능한 Nginx와 같은 프록시 서버가 URL 길이를 미리 검증하고, 일정 길이를 초과하는 요청은 내부 애플리케이션 서버로 전달하지 않고 곧바로 404 응답을 반환하도록 설정되었을 가능성이 있습니다. 이런 구현은 다음과 같은 Nginx 설정으로 가능합니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1746509698645&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;location /oauth/authorize {
    # URL 길이가 특정 값을 초과하면 404 반환
    if ($request_uri ~* &quot;^.{4000,}$&quot;) {
        return 404;
    }
    
    proxy_pass http://internal_auth_server;
}&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;그러나 414에러 대신 404에러를 뱉었다는 점을 미루어보아, 카카오의 인증 서버에는 표준과 다른 커스텀한 에러 처리 로직이 있을 가능성이 큽니다. 이에 대한 몇 가지 가능성은 다음과 같습니다.&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;b&gt;다중 계층 아키텍처&lt;/b&gt;: 외부 프록시 서버가 URL 길이를 검증하고 길이 초과 시 내부 서버로 전달하지 않고 바로 404를 반환&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안 목적&lt;/b&gt;: 414 에러는 서버의 정확한 URL 길이 제한을 노출하므로, 보안을 위해 의도적으로 모호한 404 에러를 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;라우팅 문제&lt;/b&gt;: 긴 URL이 라우팅 단계에서 &quot;존재하지 않는 리소스&quot;로 해석되어 404로 처리&lt;/li&gt;
&lt;/ol&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;카카오 로그인 API 스펙&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카카오 로그인은 OAuth 2.0 프로토콜을 기반으로 구현되어 있으며, kauth.kakao.com/oauth/authorize 엔드포인트를 통해 로그인 요청을 시작합니다. 이 과정에서 state 파라미터는 CSRF 공격 방지 및 로그인 후 상태 유지를 위해 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 카카오 개발자 문서에는 state 파라미터나 전체 URL의 길이 제한에 대한 명시적인 정보가 없습니다. 이는 카카오 로그인 API의 내부 구현이 Nginx와 같은 웹 서버에 의존하기 때문에, 웹 서버의 제한을 따르는 것으로 추정됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;h3 data-ke-size=&quot;size23&quot;&gt;1. UTM 파라미터 및 추적 코드 제거&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 간단한 해결책은 URL에서 마케팅 추적 파라미터를 제거하는 것입니다. 실제로 저희 테스트 결과, UTM 파라미터와 fbclid를 제거하자 카카오 로그인 API가 정상적으로 동작했습니다.&lt;/p&gt;
&lt;pre class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;function removeTrackingParams(url: string) {
  const urlObj = new URL(url);
  const params = urlObj.searchParams;
  
  // 추적 파라미터 제거
  ['utm_medium', 'utm_source', 'utm_campaign', 'utm_description', 
   'utm_content', 'utm_id', 'utm_term', 'fbclid'].forEach(param =&amp;gt; {
    params.delete(param);
  });
  
  return urlObj.toString();
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. State 파라미터 최적화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;state 파라미터에 포함되는 JSON 데이터를 최적화하여 불필요한 정보를 제거하고 키 이름을 줄이는 방법도 있습니다.&lt;/p&gt;
&lt;pre class=&quot;pf&quot;&gt;&lt;code&gt;function optimizeStateParam(stateObj) {
  // 필수 필드만 유지
  const optimizedState = {
    n: stateObj.next,                      // next 대신 n 사용
    m: stateObj.logMetadata?.navigation,   // metadata 간소화
    f: stateObj.from                       // from 대신 f 사용
  };
  
  // URL에서 추적 파라미터 제거
  if (optimizedState.n &amp;amp;&amp;amp; optimizedState.n.includes('?')) {
    optimizedState.n = removeTrackingParams(optimizedState.n);
  }
  if (optimizedState.f &amp;amp;&amp;amp; optimizedState.f.includes('?')) {
    optimizedState.f = removeTrackingParams(optimizedState.f);
  }
  
  return optimizedState;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 서버 측 상태 관리 (권장)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 안정적인 방법은 상태 정보를 서버에 저장하고 state 파라미터에는 짧은 식별자만 포함시키는 것입니다:&lt;/p&gt;
&lt;pre class=&quot;pf&quot;&gt;&lt;code&gt;// 클라이언트 측
async function generateStateToken(stateData) {
  try {
    const response = await fetch('/api/auth/state-token', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(stateData)
    });
    
    const { token } = await response.json();
    return token; // 짧은 토큰 반환
  } catch (error) {
    console.error('상태 토큰 생성 실패:', error);
    throw error;
  }
}

// 로그인 URL 생성
async function createKakaoLoginUrl(stateData) {
  const stateToken = await generateStateToken(stateData);
  
  return `https://kauth.kakao.com/oauth/authorize?client_id=${CLIENT_ID}&amp;amp;redirect_uri=${encodeURIComponent(REDIRECT_URI)}&amp;amp;response_type=code&amp;amp;state=${stateToken}`;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 측에서는 이 토큰과 상태 데이터를 연결하여 저장하고, 카카오 로그인 콜백에서 토큰을 통해 원래 상태를 복원합니다.&lt;/p&gt;
&lt;pre class=&quot;pf&quot;&gt;&lt;code&gt;// 서버 측 (Node.js 예시)
app.post('/api/auth/state-token', (req, res) =&amp;gt; {
  const stateData = req.body;
  const token = generateRandomToken(); // 무작위 토큰 생성
  
  // Redis나 세션 스토어에 저장 (15분 만료)
  stateStore.set(token, stateData, 60 * 15);
  
  res.json({ token });
});

app.get('/oauth/callback', (req, res) =&amp;gt; {
  const { code, state: token } = req.query;
  
  // 토큰으로 원래 상태 복원
  const originalState = stateStore.get(token);
  if (!originalState) {
    return res.status(400).send('Invalid or expired state token');
  }
  
  // 나머지 로그인 처리...
});
&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;보다 안정적인 개발을 위한 권장사항&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. URL 길이 제한 인식&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 개발 시 URL 길이 제한을 항상 염두에 두어야 합니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대부분의 서버는 URL 길이를 4KB~8KB로 제한합니다.&lt;/li&gt;
&lt;li&gt;GET 요청보다 POST 요청을 사용하여 많은 데이터를 전송하는 것이 좋습니다.&lt;/li&gt;
&lt;li&gt;특히 외부 API와 연동할 때는 URL 길이 제한을 확인하고 대비해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. OAuth 구현 시 고려사항&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;OAuth 인증 흐름을 구현할 때는 다음 사항을 고려해야 합니다:&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;/li&gt;
&lt;li&gt;CSRF 방지를 위한 랜덤 토큰은 반드시 포함시킵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 마케팅 추적과 인증 분리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마케팅 추적 매개변수(UTM)와 인증 프로세스를 분리하는 것이 좋습니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인증 요청 전에 UTM 파라미터를 분리하여 저장&lt;/li&gt;
&lt;li&gt;인증 완료 후 다시 UTM 정보를 활용하는 방식 채택&lt;/li&gt;
&lt;li&gt;분석 데이터는 쿠키나 로컬 스토리지에 임시 저장하는 방법 고려&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. 에러 처리 및 모니터링&lt;/h3&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;URL 길이 제한 오류(414)에 대한 명시적 처리&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;카카오 로그인 URL 길이 제한 문제는 Nginx의 기본 설정과 관련이 있으며, 특히 마케팅 추적 파라미터가 포함된 긴 URL을 사용할 때 나타납니다. 이 문제를 해결하기 위해서는 URL 길이를 줄이거나 서버 측 상태 관리를 도입하는 것이 효과적입니다.&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;이 경험을 통해 URL 길이 제한, OAuth 구현 방법, 그리고 보다 안정적인 웹 서비스 개발에 대한 인사이트를 얻을 수 있었습니다. 이 글이 비슷한 문제에 직면한 개발자들에게 도움이 되길 바랍니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참고 자료&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://nginx.org/en/docs/http/ngx_http_core_module.html#large_client_header_buffers&quot;&gt;Nginx 문서 - large_client_header_buffers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api&quot;&gt;카카오 개발자 문서 - 카카오 로그인&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/414&quot;&gt;HTTP 414 Request-URI Too Large 오류&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://auth0.com/docs/secure/attack-protection/state-parameters&quot;&gt;OAuth 2.0 State 파라미터 활용 가이드&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/249</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%B9%B4%EC%B9%B4%EC%98%A4-%EB%A1%9C%EA%B7%B8%EC%9D%B8-URL-%EA%B8%B8%EC%9D%B4-%EC%A0%9C%ED%95%9C-%EB%AC%B8%EC%A0%9C%EC%99%80-%ED%95%B4%EA%B2%B0%EB%B0%A9%EC%95%88#entry249comment</comments>
      <pubDate>Mon, 5 May 2025 17:47:58 +0900</pubDate>
    </item>
    <item>
      <title>Next.js에서 SEO 최적의 렌더링 전략</title>
      <link>https://hmk1022.tistory.com/entry/Nextjs%EC%97%90%EC%84%9C-SEO-%EC%B5%9C%EC%A0%81%EC%9D%98-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%A0%84%EB%9E%B5</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js 14의 App Router 환경에서는 서버 사이드 렌더링(SSR), 클라이언트 사이드 렌더링(CSR), 정적 생성(SSG), ISR 등 다양한 렌더링 방식을 상황에 맞게 조합할 수 있다. 특히 App Router는 서버 컴포넌트와 클라이언트 컴포넌트를 구분하고, 내장 fetch의 캐시 전략과 메타데이터 설정이 유연해지면서 SEO 대응 방식도 훨씬 정교해졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;611&quot; data-start=&quot;431&quot; data-ke-size=&quot;size16&quot;&gt;그중 하나가 &lt;b&gt;searchParams 기반 SSR&lt;/b&gt;이다. 기존의 다이나믹 라우트 방식과 달리, URL의 query string을 기반으로 서버에서 데이터를 받아 페이지를 렌더링하는 방식이다. 이 방식은 필터형 상품 페이지나 SKU 조합 페이지에서 매우 유용하다. 하지만 SEO 관점에서 보면 몇 가지 주의할 점이 있다.&lt;/p&gt;
&lt;p data-end=&quot;611&quot; data-start=&quot;431&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-origin-width=&quot;1000&quot; data-origin-height=&quot;571&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZVYR1/btsNyDbZDej/PHAKSkBko9Axrz80Cl5yr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZVYR1/btsNyDbZDej/PHAKSkBko9Axrz80Cl5yr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZVYR1/btsNyDbZDej/PHAKSkBko9Axrz80Cl5yr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZVYR1%2FbtsNyDbZDej%2FPHAKSkBko9Axrz80Cl5yr0%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;1000&quot; height=&quot;571&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;571&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-end=&quot;639&quot; data-start=&quot;618&quot; data-ke-size=&quot;size26&quot;&gt;렌더링 방식별 SEO 적절성 비교&lt;/h2&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;974&quot; data-start=&quot;641&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;렌더링 방식&lt;/td&gt;
&lt;td&gt;HTML 내 콘텐츠 포함 여부&lt;/td&gt;
&lt;td&gt;URL 구조&lt;/td&gt;
&lt;td&gt;SEO 적합성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;819&quot; data-start=&quot;759&quot;&gt;
&lt;td data-end=&quot;789&quot; data-start=&quot;759&quot;&gt;다이나믹 라우트 SSR&lt;br /&gt;/sku/[id]&lt;/td&gt;
&lt;td data-end=&quot;799&quot; data-start=&quot;789&quot;&gt;O (SSR)&lt;/td&gt;
&lt;td data-end=&quot;810&quot; data-start=&quot;799&quot;&gt;고유한 path&lt;/td&gt;
&lt;td data-end=&quot;819&quot; data-start=&quot;810&quot;&gt;가장 우수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;915&quot; data-start=&quot;820&quot;&gt;
&lt;td data-end=&quot;873&quot; data-start=&quot;820&quot;&gt;searchParams 기반 SSR&lt;br /&gt;/sku?plan=lte&amp;amp;color=black&lt;/td&gt;
&lt;td data-end=&quot;883&quot; data-start=&quot;873&quot;&gt;O (SSR)&lt;/td&gt;
&lt;td data-end=&quot;898&quot; data-start=&quot;883&quot;&gt;query string&lt;/td&gt;
&lt;td data-end=&quot;915&quot; data-start=&quot;898&quot;&gt;우수하나 상대적으로 약함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;974&quot; data-start=&quot;916&quot;&gt;
&lt;td data-end=&quot;940&quot; data-start=&quot;916&quot;&gt;CSR&lt;br /&gt;클라이언트에서만 fetch&lt;/td&gt;
&lt;td data-end=&quot;944&quot; data-start=&quot;940&quot;&gt;X&lt;/td&gt;
&lt;td data-end=&quot;965&quot; data-start=&quot;944&quot;&gt;URL은 다양해도 HTML엔 없음&lt;/td&gt;
&lt;td data-end=&quot;974&quot; data-start=&quot;965&quot;&gt;매우 낮음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;1031&quot; data-start=&quot;981&quot; data-ke-size=&quot;size26&quot;&gt;searchParams 기반 SSR은 왜 다이나믹 라우트 SSR보다 SEO에 약할까?&lt;/h2&gt;
&lt;h3 data-end=&quot;1051&quot; data-start=&quot;1033&quot; data-ke-size=&quot;size23&quot;&gt;1. 검색엔진의 인식 방식&lt;/h3&gt;
&lt;p data-end=&quot;1265&quot; data-start=&quot;1052&quot; data-ke-size=&quot;size16&quot;&gt;검색엔진은 보통 &lt;b&gt;URL path가 다른 페이지를 별개의 콘텐츠&lt;/b&gt;로 인식하고 인덱싱하지만,&lt;br /&gt;query string 기반 URL은 &lt;b&gt;같은 페이지의 파생된 버전&lt;/b&gt;으로 간주하는 경향이 있다.&lt;br /&gt;예를 들어 /sku?color=black&amp;amp;plan=lte와 /sku?color=white&amp;amp;plan=lte는&lt;br /&gt;검색엔진 입장에선 동일한 /sku의 일부로 판단될 수 있다.&lt;/p&gt;
&lt;p data-end=&quot;1265&quot; data-start=&quot;1052&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;1284&quot; data-start=&quot;1267&quot; data-ke-size=&quot;size23&quot;&gt;2. 중복 콘텐츠 리스크&lt;/h3&gt;
&lt;p data-end=&quot;1412&quot; data-start=&quot;1285&quot; data-ke-size=&quot;size16&quot;&gt;searchParams 조합이 많아질수록 검색엔진이 이를 중복 콘텐츠로 간주할 가능성도 커진다.&lt;br /&gt;따라서 각 조합별 페이지가 독립적인 콘텐츠임을 명확하게 하기 위해 &lt;b&gt;canonical 설정, 메타 태그 차별화&lt;/b&gt;가 필요하다.&lt;/p&gt;
&lt;p data-end=&quot;1412&quot; data-start=&quot;1285&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;1438&quot; data-start=&quot;1414&quot; data-ke-size=&quot;size23&quot;&gt;3. sitemap 자동 생성의 한계&lt;/h3&gt;
&lt;p data-end=&quot;1579&quot; data-start=&quot;1439&quot; data-ke-size=&quot;size16&quot;&gt;다이나믹 라우트는 generateStaticParams() 등을 활용해 sitemap을 자동으로 생성할 수 있다.&lt;br /&gt;반면 searchParams는 조합이 너무 많기 때문에 &lt;b&gt;URL을 수동으로 선정하거나 별도로 sitemap을 구성해야 한다.&lt;/b&gt;&lt;b&gt;&lt;/b&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-end=&quot;1579&quot; data-start=&quot;1439&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;1626&quot; data-start=&quot;1586&quot; data-ke-size=&quot;size26&quot;&gt;그렇다면 searchParams 기반 SSR은 SEO에 부적합할까?&lt;/h2&gt;
&lt;p data-end=&quot;1659&quot; data-start=&quot;1628&quot; data-ke-size=&quot;size16&quot;&gt;그렇지 않다. CSR에 비해서는 훨씬 SEO에 적합하다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1870&quot; data-start=&quot;1661&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1723&quot; data-start=&quot;1661&quot;&gt;서버 컴포넌트에서 fetch()로 데이터를 받아 렌더링하면, HTML 응답에 실질적인 콘텐츠가 포함된다.&lt;/li&gt;
&lt;li data-end=&quot;1809&quot; data-start=&quot;1724&quot;&gt;generateMetadata()를 통해 query string 기반으로 동적인 메타태그(title, description 등)를 만들 수 있다.&lt;/li&gt;
&lt;li data-end=&quot;1870&quot; data-start=&quot;1810&quot;&gt;초기 렌더링 시점에 콘텐츠가 완전하게 포함되므로 Googlebot 등은 렌더링 없이도 인덱싱이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1943&quot; data-start=&quot;1872&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;즉, CSR보다는 SEO에 훨씬 유리하며, 다이나믹 라우트만큼의 정밀도는 아니지만 실용적 수준의 대응은 충분히 가능하다.&lt;/b&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-end=&quot;1980&quot; data-start=&quot;1950&quot; data-ke-size=&quot;size26&quot;&gt;실제 적용 전략: 하이브리드 구조 + SEO 대응&lt;/h2&gt;
&lt;p data-end=&quot;2027&quot; data-start=&quot;1982&quot; data-ke-size=&quot;size16&quot;&gt;searchParams 기반의 필터/조합 페이지에서 다음과 같은 전략이 유효하다.&lt;/p&gt;
&lt;p data-end=&quot;2027&quot; data-start=&quot;1982&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;2055&quot; data-start=&quot;2029&quot; data-ke-size=&quot;size23&quot;&gt;1. SSR로 초기 진입 시 콘텐츠 포함&lt;/h3&gt;
&lt;p data-end=&quot;2111&quot; data-start=&quot;2056&quot; data-ke-size=&quot;size16&quot;&gt;서버 컴포넌트에서 searchParams를 기반으로 fetch하고, 그 결과를 HTML에 포함한다.&lt;/p&gt;
&lt;pre id=&quot;code_1745508218570&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export default async function Page({ searchParams }) {
  const data = await fetchSku(searchParams)
  return &amp;lt;SkuList data={data} /&amp;gt;
}&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 style=&quot;color: #000000; text-align: start;&quot; data-start=&quot;2029&quot; data-end=&quot;2055&quot; data-ke-size=&quot;size23&quot;&gt;2. 메타데이터는 searchParams 기반으로 동적 생성&lt;/h3&gt;
&lt;pre id=&quot;code_1745508234960&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export async function generateMetadata({ searchParams }) {
  const { plan, color } = searchParams
  return {
    title: `${plan} 요금제 - ${color} 색상 기기`,
    description: `${plan} 요금제와 ${color} 색상의 기기를 조합한 구성입니다.`,
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;2560&quot; data-start=&quot;2529&quot; data-ke-size=&quot;size23&quot;&gt;3. 주요 조합만 선택적으로 sitemap에 포함&lt;/h3&gt;
&lt;p data-end=&quot;2634&quot; data-start=&quot;2561&quot; data-ke-size=&quot;size16&quot;&gt;SEO에서 주요 조합만 노출하면 된다면, sitemap 생성 시 조합 리스트를 별도로 관리하여 명시적으로 URL을 포함시키면 된다.&lt;/p&gt;
&lt;p data-end=&quot;2634&quot; data-start=&quot;2561&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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-end=&quot;2646&quot; data-start=&quot;2641&quot; data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2926&quot; data-start=&quot;2648&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2694&quot; data-start=&quot;2648&quot;&gt;searchParams 기반 SSR은 SEO에 충분히 대응할 수 있는 방식이다.&lt;/li&gt;
&lt;li data-end=&quot;2749&quot; data-start=&quot;2695&quot;&gt;다이나믹 라우트 SSR보다는 구조적으로 인덱싱에 불리할 수 있지만, CSR보다는 확연히 낫다.&lt;/li&gt;
&lt;li data-end=&quot;2851&quot; data-start=&quot;2750&quot;&gt;중요한 것은 콘텐츠가 HTML에 렌더링되어 포함되어야 하고, generateMetadata, canonical, sitemap 등의 보완 요소를 함께 적용하는 것이다.&lt;/li&gt;
&lt;li data-end=&quot;2926&quot; data-start=&quot;2852&quot;&gt;유저 인터랙션 중심의 페이지에서는 하이브리드 전략이 적절하며, SEO가 중요한 조합만 선택적으로 대응하는 것이 실용적인 방법이다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/248</guid>
      <comments>https://hmk1022.tistory.com/entry/Nextjs%EC%97%90%EC%84%9C-SEO-%EC%B5%9C%EC%A0%81%EC%9D%98-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%A0%84%EB%9E%B5#entry248comment</comments>
      <pubDate>Fri, 25 Apr 2025 00:35:37 +0900</pubDate>
    </item>
    <item>
      <title>Next.js  상황에 맞는 렌더링 방식 선택 가이드</title>
      <link>https://hmk1022.tistory.com/entry/nextjs-%EC%83%81%ED%99%A9%EC%97%90-%EB%A7%9E%EB%8A%94-%EB%A0%8C%EB%8D%94%EB%A7%81-%EB%B0%A9%EC%8B%9D-%EC%84%A0%ED%83%9D-%EA%B0%80%EC%9D%B4%EB%93%9C</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;Next.js는 다양한 렌더링 방식을 제공합니다. 정적 생성(SSG), 서버 사이드 렌더링(SSR), 클라이언트 사이드 렌더링(CSR), 그리고 점진적 정적 생성(ISR)까지 다양한 전략이 가능하죠. 버전이 14에 도달하면서 App Router가 정식화되었고, fetch() 내장, cache, revalidate, searchParams, server/client component 분리 등 보다 유연한 방식으로 구성할 수 있게 되었습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-end=&quot;610&quot; data-start=&quot;483&quot; data-ke-size=&quot;size16&quot;&gt;하지만 기능이 다양해진 만큼 &quot;어떤 상황에서 어떤 렌더링 방식을 선택해야 하는지&quot;는 더욱 고민되는 지점입니다. 특히 실무에서 많이 마주치는 SKU 기반 조합 페이지나, 필터형 검색 결과 페이지 등에서는 의사결정이 쉽지 않습니다.&lt;/p&gt;
&lt;p data-end=&quot;663&quot; data-start=&quot;612&quot; data-ke-size=&quot;size16&quot;&gt;이번 글에서는 실제 사례를 중심으로, 어떤 렌더링 방식을 선택해야 할지를 정리해 보겠습니다.&lt;/p&gt;
&lt;p data-end=&quot;663&quot; data-start=&quot;612&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-origin-width=&quot;1000&quot; data-origin-height=&quot;571&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N5guC/btsNxC6aRqa/kYGRvW7LuFDP6beXsxxhJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N5guC/btsNxC6aRqa/kYGRvW7LuFDP6beXsxxhJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N5guC/btsNxC6aRqa/kYGRvW7LuFDP6beXsxxhJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN5guC%2FbtsNxC6aRqa%2FkYGRvW7LuFDP6beXsxxhJk%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;1000&quot; height=&quot;571&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;571&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-end=&quot;682&quot; data-start=&quot;670&quot; data-ke-size=&quot;size26&quot;&gt;렌더링 방식 정리&lt;/h2&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;
&lt;div&gt;방식설명대표 사용 상황
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100.697%; height: 182px;&quot; border=&quot;1&quot; data-end=&quot;965&quot; data-start=&quot;684&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;방식&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;설명&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;대표 사용 상황&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot; data-end=&quot;785&quot; data-start=&quot;740&quot;&gt;
&lt;td style=&quot;height: 20px;&quot; data-end=&quot;754&quot; data-start=&quot;740&quot;&gt;정적 생성 (SSG)&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot; data-end=&quot;769&quot; data-start=&quot;754&quot;&gt;빌드 시 HTML 생성&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot; data-end=&quot;785&quot; data-start=&quot;769&quot;&gt;마케팅 랜딩, 공지사항&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot; data-end=&quot;845&quot; data-start=&quot;786&quot;&gt;
&lt;td style=&quot;height: 20px;&quot; data-end=&quot;805&quot; data-start=&quot;786&quot;&gt;서버 사이드 렌더링 (SSR)&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot; data-end=&quot;825&quot; data-start=&quot;805&quot;&gt;요청 시 서버에서 HTML 생성&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot; data-end=&quot;845&quot; data-start=&quot;825&quot;&gt;로그인 필요, 맞춤형 대시보드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot; data-end=&quot;906&quot; data-start=&quot;846&quot;&gt;
&lt;td style=&quot;height: 20px;&quot; data-end=&quot;864&quot; data-start=&quot;846&quot;&gt;클라이언트 렌더링 (CSR)&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot; data-end=&quot;884&quot; data-start=&quot;864&quot;&gt;브라우저에서 fetch 후 렌더&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot; data-end=&quot;906&quot; data-start=&quot;884&quot;&gt;인터랙션 위주 페이지, 설정/필터&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot; data-end=&quot;965&quot; data-start=&quot;907&quot;&gt;
&lt;td style=&quot;height: 20px;&quot; data-end=&quot;926&quot; data-start=&quot;907&quot;&gt;ISR (revalidate)&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot; data-end=&quot;946&quot; data-start=&quot;926&quot;&gt;일정 주기로 정적 페이지 재생성&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot; data-end=&quot;965&quot; data-start=&quot;946&quot;&gt;실시간성이 낮은 상품 페이지&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;994&quot; data-start=&quot;972&quot; data-ke-size=&quot;size26&quot;&gt;SKU/옵션 조합 페이지에서의 고민&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;887&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uZlTr/btsNxYHMBX5/r77COd8VLzZMiQ1uLIFV1K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uZlTr/btsNxYHMBX5/r77COd8VLzZMiQ1uLIFV1K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uZlTr/btsNxYHMBX5/r77COd8VLzZMiQ1uLIFV1K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuZlTr%2FbtsNxYHMBX5%2Fr77COd8VLzZMiQ1uLIFV1K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;405&quot; height=&quot;745&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;887&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-end=&quot;1117&quot; data-start=&quot;996&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1117&quot; data-start=&quot;996&quot; data-ke-size=&quot;size16&quot;&gt;실무에서는 핸드폰, 노트북 등 상품을 선택할 때 &quot;기기 + 요금제 + 색상&quot; 같은 &lt;b&gt;옵션 조합&lt;/b&gt;에 따라 화면이 바뀌는 구조를 자주 마주칩니다. 이 경우 페이지 설계 방향은 다음 두 가지 중 하나로 갈 수 있습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1211&quot; data-start=&quot;1119&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1151&quot; data-start=&quot;1119&quot;&gt;다이나믹 라우트 기반 SSR (/sku/[id])&lt;/li&gt;
&lt;li data-end=&quot;1211&quot; data-start=&quot;1152&quot;&gt;searchParams 기반 SSR 또는 CSR (/sku?plan=lte&amp;amp;color=black)&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-end=&quot;1258&quot; data-start=&quot;1218&quot; data-ke-size=&quot;size26&quot;&gt;다이나믹 라우트 SSR vs searchParams 기반 구조 비교&lt;/h2&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;1633&quot; data-start=&quot;1260&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 21.0465%;&quot;&gt;항목&lt;/td&gt;
&lt;td style=&quot;width: 30.3489%;&quot;&gt;다이나믹 라우트 SSR&lt;/td&gt;
&lt;td style=&quot;width: 48.4883%;&quot;&gt;searchParams 기반&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1411&quot; data-start=&quot;1353&quot;&gt;
&lt;td style=&quot;width: 21.0465%;&quot; data-end=&quot;1362&quot; data-start=&quot;1353&quot;&gt;URL 형태&lt;/td&gt;
&lt;td style=&quot;width: 30.3489%;&quot; data-end=&quot;1378&quot; data-start=&quot;1362&quot;&gt;/sku/iphone15&lt;/td&gt;
&lt;td style=&quot;width: 48.4883%;&quot; data-end=&quot;1411&quot; data-start=&quot;1378&quot;&gt;/sku?device=iphone15&amp;amp;plan=lte&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1458&quot; data-start=&quot;1412&quot;&gt;
&lt;td style=&quot;width: 21.0465%;&quot; data-end=&quot;1426&quot; data-start=&quot;1412&quot;&gt;서버 fetch 방식&lt;/td&gt;
&lt;td style=&quot;width: 30.3489%;&quot; data-end=&quot;1439&quot; data-start=&quot;1426&quot;&gt;params로 식별&lt;/td&gt;
&lt;td style=&quot;width: 48.4883%;&quot; data-end=&quot;1458&quot; data-start=&quot;1439&quot;&gt;searchParams 파싱&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1496&quot; data-start=&quot;1459&quot;&gt;
&lt;td style=&quot;width: 21.0465%;&quot; data-end=&quot;1465&quot; data-start=&quot;1459&quot;&gt;SEO&lt;/td&gt;
&lt;td style=&quot;width: 30.3489%;&quot; data-end=&quot;1483&quot; data-start=&quot;1465&quot;&gt;매우 우수 (경로별 인덱싱)&lt;/td&gt;
&lt;td style=&quot;width: 48.4883%;&quot; data-end=&quot;1496&quot; data-start=&quot;1483&quot;&gt;상대적으로 제한적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1539&quot; data-start=&quot;1497&quot;&gt;
&lt;td style=&quot;width: 21.0465%;&quot; data-end=&quot;1509&quot; data-start=&quot;1497&quot;&gt;조합 수 많을 때&lt;/td&gt;
&lt;td style=&quot;width: 30.3489%;&quot; data-end=&quot;1525&quot; data-start=&quot;1509&quot;&gt;URL 폭발 가능성 있음&lt;/td&gt;
&lt;td style=&quot;width: 48.4883%;&quot; data-end=&quot;1539&quot; data-start=&quot;1525&quot;&gt;유연하게 대응 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1590&quot; data-start=&quot;1540&quot;&gt;
&lt;td style=&quot;width: 21.0465%;&quot; data-end=&quot;1555&quot; data-start=&quot;1540&quot;&gt;UX (옵션 변경 시)&lt;/td&gt;
&lt;td style=&quot;width: 30.3489%;&quot; data-end=&quot;1567&quot; data-start=&quot;1555&quot;&gt;페이지 이동 필요&lt;/td&gt;
&lt;td style=&quot;width: 48.4883%;&quot; data-end=&quot;1590&quot; data-start=&quot;1567&quot;&gt;URL만 바꾸고 데이터만 교체 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1633&quot; data-start=&quot;1591&quot;&gt;
&lt;td style=&quot;width: 21.0465%;&quot; data-end=&quot;1600&quot; data-start=&quot;1591&quot;&gt;캐시 최적화&lt;/td&gt;
&lt;td style=&quot;width: 30.3489%;&quot; data-end=&quot;1609&quot; data-start=&quot;1600&quot;&gt;ISR 가능&lt;/td&gt;
&lt;td style=&quot;width: 48.4883%;&quot; data-end=&quot;1633&quot; data-start=&quot;1609&quot;&gt;캐시 활용은 fetch 조합 기반으로 (reavalidate)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론적으로, 옵션 조합이 매우 다양해질 가능성이 높고 유저가 선택을 반복적으로 할 수 있는 구조라면 searchParams 기반으로 렌더링 구조를 잡는 것이 더 효율적일 수 있습니다.&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-end=&quot;1769&quot; data-start=&quot;1741&quot; data-ke-size=&quot;size26&quot;&gt;다른 방법: SSR + CSR 하이브리드 방식&lt;/h2&gt;
&lt;p data-end=&quot;1892&quot; data-start=&quot;1771&quot; data-ke-size=&quot;size16&quot;&gt;Next.js 14의 App Router에서는 서버 컴포넌트에서 SSR을 처리하고, 클라이언트 컴포넌트에서는 React Query 같은 라이브러리를 활용해 CSR 렌더링을 적용하는 &lt;b&gt;하이브리드 방식&lt;/b&gt;이 가능합니다.&lt;/p&gt;
&lt;h3 data-end=&quot;1903&quot; data-start=&quot;1894&quot; data-ke-size=&quot;size23&quot;&gt;구조 요약&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;2036&quot; data-start=&quot;1905&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;1953&quot; data-start=&quot;1905&quot;&gt;첫 진입 시에는 SSR로 searchParams 기반 데이터를 서버에서 가져옴&lt;/li&gt;
&lt;li data-end=&quot;2003&quot; data-start=&quot;1954&quot;&gt;이후 사용자가 요금제, 컬러 등을 변경하면 CSR(fetch) 방식으로 화면만 바뀜&lt;/li&gt;
&lt;li data-end=&quot;2036&quot; data-start=&quot;2004&quot;&gt;URL은 항상 현재 조합을 반영하고 있어 공유 가능함&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1745506989648&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// app/sku/page.tsx
import { fetchSku } from '@/lib/api'
import SkuClient from './SkuClient'

export default async function Page({ searchParams }) {
  const data = await fetchSku(searchParams)
  return &amp;lt;SkuClient initialData={data} initialParams={searchParams} /&amp;gt;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1745506997025&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// app/sku/SkuClient.tsx
'use client'

import { useQuery } from '@tanstack/react-query'
import { useSearchParams, useRouter } from 'next/navigation'

export default function SkuClient({ initialData, initialParams }) {
  const router = useRouter()
  const params = useSearchParams()

  const queryKey = ['sku', params.toString()]
  const { data } = useQuery({
    queryKey,
    queryFn: () =&amp;gt; fetch(`/api/sku?${params}`).then(res =&amp;gt; res.json()),
    initialData,
  })

  const handleChange = (newParams) =&amp;gt; {
    router.replace(`?${newParams.toString()}`)
  }

  return (
    &amp;lt;&amp;gt;
      &amp;lt;OptionSelector onChange={handleChange} /&amp;gt;
      &amp;lt;SkuViewer data={data} /&amp;gt;
    &amp;lt;/&amp;gt;
  )
}&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;size18&quot;&gt;&lt;b&gt;CSR 하이브리드 구조에서 클라이언트 컴포넌트가 메인 콘텐츠를 담당하면, &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;그 부분은 HTML로 SSR 되지 않아 SEO가 약해지는 것 아닌가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;217&quot; data-start=&quot;206&quot; data-ke-size=&quot;size26&quot;&gt;핵심 정리 먼저&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;515&quot; data-start=&quot;219&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;340&quot; data-start=&quot;219&quot;&gt;✅ &lt;b&gt;맞습니다&lt;/b&gt;: 클라이언트 컴포넌트 내부에서만 콘텐츠를 fetch해 렌더링하면, &lt;b&gt;HTML에 해당 콘텐츠가 포함되지 않기 때문에&lt;/b&gt; 검색엔진(특히 Googlebot)이 제대로 인덱싱하지 못할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;414&quot; data-start=&quot;341&quot;&gt;✅ &lt;b&gt;맞습니다&lt;/b&gt;: 반대로 서버 컴포넌트만으로 구성하면 HTML에 실제 콘텐츠가 포함되므로 &lt;b&gt;SEO에 훨씬 유리&lt;/b&gt;합니다.&lt;/li&gt;
&lt;li data-end=&quot;515&quot; data-start=&quot;415&quot;&gt;✅ &lt;b&gt;맞습니다&lt;/b&gt;: 클릭 가능한 요소(Link)만 있다면 그것은 클라이언트 컴포넌트일 필요는 없습니다. &lt;b&gt;&amp;lt;Link&amp;gt;는 서버 컴포넌트에서도 사용할 수 있습니다&lt;/b&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;CSR 하이브리드 구조의 SEO 한계&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1745507768808&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 예: 클라이언트 컴포넌트 내부에서만 데이터 fetch
'use client'

const Page = () =&amp;gt; {
  const [data, setData] = useState(null)
  useEffect(() =&amp;gt; {
    fetch('/api/sku?plan=lte&amp;amp;color=black').then(res =&amp;gt; res.json()).then(setData)
  }, [])

  return &amp;lt;&amp;gt;{data?.title}&amp;lt;/&amp;gt;
}&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;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;976&quot; data-start=&quot;843&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;867&quot; data-start=&quot;843&quot;&gt;&lt;b&gt;초기 HTML에는 data가 없음&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;901&quot; data-start=&quot;868&quot;&gt;검색엔진이 이 페이지를 방문해도 콘텐츠를 못 보고 지나침&lt;/li&gt;
&lt;li data-end=&quot;976&quot; data-start=&quot;902&quot;&gt;CSR로만 구성된 콘텐츠는 &lt;b&gt;SEO 측면에서는 거의 의미 없음&lt;/b&gt; (특히 meta tag와 og tag도 CSR이면 의미 없음)&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;&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js App Router에서 &amp;lt;Link&amp;gt; 같은 인터랙션 컴포넌트는 서버 컴포넌트에서도 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1745507810206&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 서버 컴포넌트에서도 사용 가능
&amp;lt;Link href=&quot;/sku?plan=lte&amp;amp;color=black&quot;&amp;gt;이 요금제 보기&amp;lt;/Link&amp;gt;&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;lt;Link&amp;gt; 자체는 클라이언트에서 hydrate되지만, HTML은 서버에서 내려오기 때문에 &lt;b&gt;SEO 노출에도 전혀 문제 없습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;1283&quot; data-start=&quot;1265&quot; data-ke-size=&quot;size26&quot;&gt;그럼 더 나은 방법은?&lt;/h2&gt;
&lt;p data-end=&quot;1297&quot; data-start=&quot;1285&quot; data-ke-size=&quot;size16&quot;&gt;당신이 원하시는 것이:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1346&quot; data-start=&quot;1299&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1310&quot; data-start=&quot;1299&quot;&gt;SEO 잘 되면서&lt;/li&gt;
&lt;li data-end=&quot;1327&quot; data-start=&quot;1311&quot;&gt;인터랙션 UX도 자연스럽고&lt;/li&gt;
&lt;li data-end=&quot;1346&quot; data-start=&quot;1328&quot;&gt;서버 부하도 최소화하고 싶다면&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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;추천 구조: 서버 컴포넌트 SSR + 부분적 클라이언트 CSR&lt;/h3&gt;
&lt;pre id=&quot;code_1745507859626&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// /app/sku/page.tsx (서버 컴포넌트)
import { fetchSku } from '@/lib/api'
import { SkuList } from './SkuList'

export default async function Page({ searchParams }) {
  const data = await fetchSku(searchParams) // SSR 시점에 데이터 fetch됨
  return (
    &amp;lt;&amp;gt;
      &amp;lt;h1&amp;gt;{data.title}&amp;lt;/h1&amp;gt; {/* HTML에 포함되어 인덱싱 가능 */}
      &amp;lt;SkuList data={data.items} /&amp;gt;
    &amp;lt;/&amp;gt;
  )
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1745507871515&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// SkuList.tsx (클라이언트 컴포넌트 아님)
import Link from 'next/link'

export function SkuList({ data }) {
  return (
    &amp;lt;ul&amp;gt;
      {data.map(item =&amp;gt; (
        &amp;lt;li key={item.id}&amp;gt;
          &amp;lt;Link href={`?plan=${item.plan}&amp;amp;color=${item.color}`}&amp;gt;{item.name}&amp;lt;/Link&amp;gt;
        &amp;lt;/li&amp;gt;
      ))}
    &amp;lt;/ul&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-end=&quot;2083&quot; data-start=&quot;2074&quot; data-ke-size=&quot;size23&quot;&gt;핵심 특징&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2241&quot; data-start=&quot;2084&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2128&quot; data-start=&quot;2084&quot;&gt;메인 콘텐츠는 서버에서 fetch 되어 HTML에 포함 &amp;rarr; SEO 매우 우수&lt;/li&gt;
&lt;li data-end=&quot;2171&quot; data-start=&quot;2129&quot;&gt;클릭 가능한 요소는 서버 컴포넌트에서도 &amp;lt;Link&amp;gt;로 자연스럽게 처리&lt;/li&gt;
&lt;li data-end=&quot;2241&quot; data-start=&quot;2172&quot;&gt;선택 이벤트 처리만 필요한 곳에 use client를 붙인 클라이언트 컴포넌트를 사용 (예: 옵션 선택 슬라이더 등)&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-end=&quot;3031&quot; data-start=&quot;3014&quot; data-ke-size=&quot;size26&quot;&gt;언제 어떤 방식이 적합한가&lt;/h2&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;/span&gt;
&lt;div&gt;&lt;br /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;3283&quot; data-start=&quot;3033&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;상황&amp;nbsp;&lt;/td&gt;
&lt;td&gt;추천 방식&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;3104&quot; data-start=&quot;3069&quot;&gt;
&lt;td data-end=&quot;3089&quot; data-start=&quot;3069&quot;&gt;고정된 콘텐츠, 마케팅성 페이지&lt;/td&gt;
&lt;td data-end=&quot;3104&quot; data-start=&quot;3089&quot;&gt;SSG (정적 생성)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;3151&quot; data-start=&quot;3105&quot;&gt;
&lt;td data-end=&quot;3125&quot; data-start=&quot;3105&quot;&gt;로그인 필요, 세션 기반 페이지&lt;/td&gt;
&lt;td data-end=&quot;3151&quot; data-start=&quot;3125&quot;&gt;SSR (server component)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;3196&quot; data-start=&quot;3152&quot;&gt;
&lt;td data-end=&quot;3172&quot; data-start=&quot;3152&quot;&gt;실시간 옵션 선택이 많은 페이지&lt;/td&gt;
&lt;td data-end=&quot;3196&quot; data-start=&quot;3172&quot;&gt;CSR 또는 SSR+CSR 하이브리드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;3236&quot; data-start=&quot;3197&quot;&gt;
&lt;td data-end=&quot;3213&quot; data-start=&quot;3197&quot;&gt;검색 필터, 리스트 결과&lt;/td&gt;
&lt;td data-end=&quot;3236&quot; data-start=&quot;3213&quot;&gt;searchParams 기반 CSR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;3283&quot; data-start=&quot;3237&quot;&gt;
&lt;td data-end=&quot;3260&quot; data-start=&quot;3237&quot;&gt;SEO 최적화 필요 + 경로별 인덱싱&lt;/td&gt;
&lt;td data-end=&quot;3283&quot; data-start=&quot;3260&quot;&gt;다이나믹 라우트 SSR 또는 ISR&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-end=&quot;3296&quot; data-start=&quot;3290&quot; data-ke-size=&quot;size26&quot;&gt;마치며&lt;/h2&gt;
&lt;p data-end=&quot;3433&quot; data-start=&quot;3298&quot; data-ke-size=&quot;size16&quot;&gt;Next.js 14는 SSR과 CSR, 그리고 정적 생성 방식들을 상황에 따라 혼합할 수 있는 매우 유연한 아키텍처를 제공합니다. 중요한 것은 성능 최적화나 개발 편의성보다 &lt;b&gt;사용자 경험과 비즈니스 목표에 맞는 구조를 선택&lt;/b&gt;하는 것입니다.&lt;/p&gt;
&lt;p data-end=&quot;3433&quot; data-start=&quot;3298&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;3544&quot; data-start=&quot;3435&quot; data-ke-size=&quot;size16&quot;&gt;특히 선택 조합이 많은 SKU 페이지처럼 복잡한 UX를 다루는 경우, searchParams 기반 SSR + CSR 구조가 성능과 UX, 유지보수성 모두에서 매우 이상적인 선택이 될 수 있습니다.&lt;/p&gt;</description>
      <category>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/247</guid>
      <comments>https://hmk1022.tistory.com/entry/nextjs-%EC%83%81%ED%99%A9%EC%97%90-%EB%A7%9E%EB%8A%94-%EB%A0%8C%EB%8D%94%EB%A7%81-%EB%B0%A9%EC%8B%9D-%EC%84%A0%ED%83%9D-%EA%B0%80%EC%9D%B4%EB%93%9C#entry247comment</comments>
      <pubDate>Fri, 25 Apr 2025 00:19:28 +0900</pubDate>
    </item>
    <item>
      <title>Next.js 서버사이드 keep alive</title>
      <link>https://hmk1022.tistory.com/entry/Nextjs-%EC%84%9C%EB%B2%84%EC%82%AC%EC%9D%B4%EB%93%9C-keep-alive</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;Next.js 프로젝트에서 백엔드 API와 통신할 때, 우리는 종종 브라우저 또는 서버(SSR/API 라우트 등)에서 외부 서버로 HTTP 요청을 보냅니다. 이때 성능 최적화를 고려한다면 &lt;b&gt;&quot;keep-alive&quot; 설정&lt;/b&gt;을 살펴볼 필요가 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;303&quot; data-start=&quot;286&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;390&quot; data-start=&quot;305&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;390&quot; data-start=&quot;305&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;335&quot; data-start=&quot;305&quot;&gt;브라우저에서 keep-alive는 어떻게 작동할까?&lt;/li&gt;
&lt;li data-end=&quot;369&quot; data-start=&quot;336&quot;&gt;서버 &amp;rarr; 서버 요청에서는 왜 명시적으로 설정이 필요할까?&lt;/li&gt;
&lt;li data-end=&quot;390&quot; data-start=&quot;370&quot;&gt;실제로 어떻게 적용할 수 있을까?&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;420&quot; data-start=&quot;397&quot; data-ke-size=&quot;size26&quot;&gt;HTTP keep-alive란?&lt;/h2&gt;
&lt;p data-end=&quot;449&quot; data-start=&quot;422&quot; data-ke-size=&quot;size16&quot;&gt;기본적으로 HTTP 요청은 다음 흐름을 따릅니다:&lt;/p&gt;
&lt;blockquote data-end=&quot;483&quot; data-start=&quot;451&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;483&quot; data-start=&quot;453&quot; data-ke-size=&quot;size16&quot;&gt;연결 열기 &amp;rarr; 요청 보내기 &amp;rarr; 응답 받기 &amp;rarr; 연결 닫기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;587&quot; data-start=&quot;485&quot; data-ke-size=&quot;size16&quot;&gt;이런 구조는 요청마다 &lt;b&gt;새로운 TCP 연결을 만들고 끊는 비효율&lt;/b&gt;을 초래합니다. 특히, 서버 &amp;rarr; 서버 간에 수백~수천 개의 API 호출이 일어난다면 이 비용은 무시할 수 없습니다.&lt;/p&gt;
&lt;p data-end=&quot;673&quot; data-start=&quot;589&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;keep-alive&lt;/b&gt;는 이 문제를 해결하는 방식입니다. 한 번 연결한 TCP 소켓을 &lt;b&gt;재사용&lt;/b&gt;해서 여러 HTTP 요청을 보낼 수 있게 합니다.&lt;/p&gt;
&lt;hr data-end=&quot;678&quot; data-start=&quot;675&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;703&quot; data-start=&quot;680&quot; data-ke-size=&quot;size26&quot;&gt;브라우저에서는 어떻게 동작할까?&lt;/h2&gt;
&lt;p data-end=&quot;845&quot; data-start=&quot;705&quot; data-ke-size=&quot;size16&quot;&gt;브라우저는 기본적으로 HTTP/1.1을 기반으로 하기 때문에, &lt;b&gt;keep-alive는 디폴트로 활성화&lt;/b&gt;되어 있습니다.&lt;br /&gt;즉, 클라이언트 사이드에서 fetch, axios 등을 통해 요청을 보낼 때는 특별한 설정 없이도 연결이 재사용됩니다.&lt;/p&gt;
&lt;p data-end=&quot;875&quot; data-start=&quot;847&quot; data-ke-size=&quot;size16&quot;&gt;하지만 이 연결은 브라우저가 내부적으로 관리합니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;943&quot; data-start=&quot;877&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;898&quot; data-start=&quot;877&quot;&gt;같은 origin 요청끼리만 재사용&lt;/li&gt;
&lt;li data-end=&quot;923&quot; data-start=&quot;899&quot;&gt;연결 수 제한 있음 (도메인당 6개 등)&lt;/li&gt;
&lt;li data-end=&quot;943&quot; data-start=&quot;924&quot;&gt;idle timeout이 적용됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1001&quot; data-start=&quot;945&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;요약&lt;/b&gt;: 브라우저는 알아서 keep-alive를 잘 관리하니, 따로 설정할 필요는 없습니다.&lt;/p&gt;
&lt;hr data-end=&quot;1006&quot; data-start=&quot;1003&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1029&quot; data-start=&quot;1008&quot; data-ke-size=&quot;size26&quot;&gt;서버 &amp;rarr; 서버 요청에서는?&lt;/h2&gt;
&lt;p data-end=&quot;1133&quot; data-start=&quot;1031&quot; data-ke-size=&quot;size16&quot;&gt;반대로, &lt;b&gt;Next.js 서버에서 실행되는 코드 (예: getServerSideProps, API Route 등)&lt;/b&gt; 는 Node.js의 http 모듈을 기반으로 동작합니다.&lt;/p&gt;
&lt;p data-end=&quot;1208&quot; data-start=&quot;1135&quot; data-ke-size=&quot;size16&quot;&gt;Node.js의 기본 설정은 keepAlive: false이기 때문에, &lt;b&gt;매 요청마다 TCP 연결을 새로 생성&lt;/b&gt;하게 됩니다.&lt;/p&gt;
&lt;p data-end=&quot;1235&quot; data-start=&quot;1210&quot; data-ke-size=&quot;size16&quot;&gt;이럴 경우 다음을 명시적으로 설정해야 합니다:&lt;/p&gt;
&lt;p data-end=&quot;1235&quot; data-start=&quot;1210&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1235&quot; data-start=&quot;1210&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;1274&quot; data-start=&quot;1237&quot; data-ke-size=&quot;size23&quot;&gt;1. node-fetch + http.Agent&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1745302667390&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import fetch from 'node-fetch';
import http from 'http';

const keepAliveAgent = new http.Agent({ keepAlive: true });

await fetch('https://api.example.com/data', {
  agent: keepAliveAgent,
});&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-end=&quot;1517&quot; data-start=&quot;1480&quot; data-ke-size=&quot;size23&quot;&gt;2. undici &amp;ndash; 더 빠르고 공식 추천되는 방식&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1745302740068&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { fetch, Agent } from 'undici';

const agent = new Agent({
  keepAliveTimeout: 10_000,      // idle 상태에서 유지할 시간
  keepAliveMaxTimeout: 15_000,   // 최대 연결 유지 시간
});

await fetch('https://api.example.com/data', {
  dispatcher: agent,
});&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-end=&quot;1794&quot; data-start=&quot;1772&quot; data-ke-size=&quot;size23&quot;&gt;3. axios 사용 시&lt;/h3&gt;
&lt;pre id=&quot;code_1745302750163&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import axios from 'axios';
import http from 'http';

const httpAgent = new http.Agent({ keepAlive: true });

const response = await axios.get('https://api.example.com/data', {
  httpAgent,
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;2033&quot; data-start=&quot;2004&quot; data-ke-size=&quot;size26&quot;&gt;언제 keep-alive를 쓰는 게 좋을까?&lt;/h2&gt;
&lt;p data-end=&quot;2061&quot; data-start=&quot;2035&quot; data-ke-size=&quot;size16&quot;&gt;다음 조건에 해당한다면 적극 도입을 고려하세요:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2183&quot; data-start=&quot;2063&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2118&quot; data-start=&quot;2063&quot;&gt;&lt;b&gt;같은 서버에 반복적으로 요청&lt;/b&gt;하는 구조 (ex. 내부 API Gateway, 백엔드 서버)&lt;/li&gt;
&lt;li data-end=&quot;2154&quot; data-start=&quot;2119&quot;&gt;&lt;b&gt;대량의 API 호출&lt;/b&gt;이 한 페이지 내에서 이뤄지는 구조&lt;/li&gt;
&lt;li data-end=&quot;2183&quot; data-start=&quot;2155&quot;&gt;&lt;b&gt;SSR에서 응답 속도 개선&lt;/b&gt;이 필요한 경우&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;2188&quot; data-start=&quot;2185&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2199&quot; data-start=&quot;2190&quot; data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2351&quot; data-start=&quot;2201&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2245&quot; data-start=&quot;2201&quot;&gt;브라우저는 keep-alive를 자동으로 관리하므로 따로 신경 쓸 필요 없음&lt;/li&gt;
&lt;li data-end=&quot;2294&quot; data-start=&quot;2246&quot;&gt;서버 측에서는 Agent를 직접 설정하지 않으면 요청마다 새로운 TCP 연결이 열림&lt;/li&gt;
&lt;li data-end=&quot;2351&quot; data-start=&quot;2295&quot;&gt;&lt;b&gt;keep-alive 설정만으로도 평균 요청 시간이나 서버 부하가 눈에 띄게 개선&lt;/b&gt;될 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;2356&quot; data-start=&quot;2353&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-end=&quot;2489&quot; data-start=&quot;2358&quot; data-ke-size=&quot;size16&quot;&gt;팀에서 성능 개선을 논의 중이라면, 이 설정이 적용되어 있는지 한번 확인해보세요.&lt;br /&gt;특히 getServerSideProps, API Route, 혹은 백엔드 간 통신을 자주 쓰는 구조라면 꽤 큰 차이를 만들어낼 수 있습니다.&lt;/p&gt;</description>
      <category>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/246</guid>
      <comments>https://hmk1022.tistory.com/entry/Nextjs-%EC%84%9C%EB%B2%84%EC%82%AC%EC%9D%B4%EB%93%9C-keep-alive#entry246comment</comments>
      <pubDate>Tue, 22 Apr 2025 15:22:11 +0900</pubDate>
    </item>
    <item>
      <title>프로그래밍에서 Buffer란?</title>
      <link>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%97%90%EC%84%9C-Buffer%EB%9E%80</link>
      <description>&lt;h3 data-end=&quot;23&quot; data-start=&quot;0&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;프로그래밍에서의 Buffer&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;93&quot; data-start=&quot;24&quot; data-ke-size=&quot;size16&quot;&gt;Buffer(버퍼)는 데이터를 임시로 저장하는 메모리 공간을 의미합니다. 일반적으로 다음과 같은 목적으로 사용됩니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;501&quot; data-start=&quot;95&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;255&quot; data-start=&quot;95&quot;&gt;&lt;b&gt;속도 차이 해결&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;255&quot; data-start=&quot;116&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;216&quot; data-start=&quot;116&quot;&gt;CPU, 메모리, 디스크, 네트워크 등의 장치는 서로 다른 속도로 데이터를 처리합니다. 버퍼를 사용하면 빠른 장치가 느린 장치를 기다리지 않고 계속 작업을 수행할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;255&quot; data-start=&quot;220&quot;&gt;예: 키보드 입력 버퍼, 그래픽 렌더링 버퍼, 스트리밍 버퍼&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;351&quot; data-start=&quot;257&quot;&gt;&lt;b&gt;데이터 변환 및 가공&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;351&quot; data-start=&quot;281&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;325&quot; data-start=&quot;281&quot;&gt;데이터를 일정한 크기로 나누거나, 변환할 때 중간 저장소 역할을 합니다.&lt;/li&gt;
&lt;li data-end=&quot;351&quot; data-start=&quot;329&quot;&gt;예: 동영상 인코딩, 오디오 프로세싱&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;501&quot; data-start=&quot;353&quot;&gt;&lt;b&gt;I/O 성능 최적화&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;501&quot; data-start=&quot;376&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;452&quot; data-start=&quot;376&quot;&gt;디스크나 네트워크와 같은 느린 장치에서 데이터 입출력을 할 때, 여러 번의 작은 작업을 모아 한 번에 처리하면 성능이 향상됩니다.&lt;/li&gt;
&lt;li data-end=&quot;501&quot; data-start=&quot;456&quot;&gt;예: 파일 시스템의 디스크 캐시(Buffer Cache), 네트워크 패킷 버퍼&lt;/li&gt;
&lt;/ul&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;h3 data-end=&quot;543&quot; data-start=&quot;508&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;운영체제에서 네트워크 통신 시 Buffer의 역할&lt;/b&gt;&lt;/h3&gt;
&lt;p data-end=&quot;610&quot; data-start=&quot;544&quot; data-ke-size=&quot;size16&quot;&gt;운영체제가 네트워크 통신을 할 때, 버퍼는 &lt;b&gt;송신(Send) 버퍼&lt;/b&gt;와 &lt;b&gt;수신(Receive) 버퍼&lt;/b&gt;로 나뉩니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1078&quot; data-start=&quot;612&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;860&quot; data-start=&quot;612&quot;&gt;&lt;b&gt;송신 버퍼(Send Buffer)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;860&quot; data-start=&quot;643&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;717&quot; data-start=&quot;643&quot;&gt;애플리케이션이 보낼 데이터를 운영체제(커널)에 전달하면, 운영체제는 이 데이터를 네트워크 인터페이스에 적절히 분배하여 전송합니다.&lt;/li&gt;
&lt;li data-end=&quot;794&quot; data-start=&quot;721&quot;&gt;네트워크가 혼잡하거나 수신 측이 데이터를 바로 받을 수 없는 경우, 버퍼에서 데이터를 잠시 저장했다가 적절한 시점에 전송합니다.&lt;/li&gt;
&lt;li data-end=&quot;860&quot; data-start=&quot;798&quot;&gt;TCP의 경우, &lt;b&gt;TCP Send Buffer&lt;/b&gt;에 데이터가 쌓이고, 적절한 패킷 크기로 나눠 전송됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;1078&quot; data-start=&quot;862&quot;&gt;&lt;b&gt;수신 버퍼(Receive Buffer)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1078&quot; data-start=&quot;896&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;934&quot; data-start=&quot;896&quot;&gt;네트워크에서 받은 데이터를 운영체제(커널)가 저장하는 공간입니다.&lt;/li&gt;
&lt;li data-end=&quot;989&quot; data-start=&quot;938&quot;&gt;애플리케이션이 데이터를 처리할 준비가 되면 운영체제는 수신 버퍼에서 데이터를 전달합니다.&lt;/li&gt;
&lt;li data-end=&quot;1078&quot; data-start=&quot;993&quot;&gt;TCP의 경우, &lt;b&gt;TCP Receive Buffer&lt;/b&gt;에 데이터가 쌓이고, 애플리케이션이 recv() 같은 함수를 호출하면 데이터를 가져갑니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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-end=&quot;204&quot; data-start=&quot;183&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;왜 버퍼가 필요한가?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-end=&quot;226&quot; data-start=&quot;205&quot; data-ke-size=&quot;size16&quot;&gt;네트워크에서 데이터를 송수신할 때,&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;393&quot; data-start=&quot;227&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;282&quot; data-start=&quot;227&quot;&gt;&lt;b&gt;CPU와 네트워크 속도가 다름&lt;/b&gt; &amp;rarr; CPU는 매우 빠르지만, 네트워크는 상대적으로 느림&lt;/li&gt;
&lt;li data-end=&quot;333&quot; data-start=&quot;283&quot;&gt;&lt;b&gt;패킷이 한 번에 도착하지 않음&lt;/b&gt; &amp;rarr; 데이터가 여러 개의 패킷으로 나뉘어 전송됨&lt;/li&gt;
&lt;li data-end=&quot;393&quot; data-start=&quot;334&quot;&gt;&lt;b&gt;애플리케이션이 즉시 처리하지 못할 수도 있음&lt;/b&gt; &amp;rarr; 받은 데이터를 즉시 사용하지 않을 수도 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;466&quot; data-start=&quot;395&quot; data-ke-size=&quot;size16&quot;&gt;이런 문제를 해결하기 위해 &lt;b&gt;운영체제는 네트워크 데이터를 버퍼에 저장하고, 애플리케이션이 필요할 때 가져가도록 처리&lt;/b&gt;합니다.&lt;/p&gt;
&lt;p data-end=&quot;466&quot; data-start=&quot;395&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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-end=&quot;510&quot; data-start=&quot;473&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;송신(Tx)과 수신(Rx)에서의 Buffer 역할&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-end=&quot;542&quot; data-start=&quot;511&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;(1) 송신 버퍼 (Send Buffer)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;700&quot; data-start=&quot;543&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;607&quot; data-start=&quot;543&quot;&gt;애플리케이션이 네트워크로 데이터를 보내면, 운영체제의 &lt;b&gt;송신 버퍼(Send Buffer)&lt;/b&gt;에 먼저 저장됨&lt;/li&gt;
&lt;li data-end=&quot;665&quot; data-start=&quot;608&quot;&gt;네트워크 장치는 버퍼에서 데이터를 가져가 일정 크기의 &lt;b&gt;패킷(packet)&lt;/b&gt;으로 나누어 송신&lt;/li&gt;
&lt;li data-end=&quot;700&quot; data-start=&quot;666&quot;&gt;데이터가 성공적으로 전송되면, 해당 버퍼 공간이 해제됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;732&quot; data-start=&quot;702&quot; data-ke-size=&quot;size16&quot;&gt;  &lt;b&gt;예제: 송신 버퍼에서 데이터를 보내는 과정&lt;/b&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1742698982207&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;애플리케이션 &amp;rarr; 송신 버퍼 (운영체제) &amp;rarr; 네트워크 카드(NIC) &amp;rarr; 인터넷 전송&lt;/code&gt;&lt;/pre&gt;
&lt;span&gt;&lt;span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;902&quot; data-start=&quot;803&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;송신 버퍼가 가득 차면?&lt;/b&gt;&lt;br /&gt;&amp;rarr; 애플리케이션이 새로운 데이터를 쓰려고 해도 &lt;b&gt;대기(blocking)&lt;/b&gt; 해야 함&lt;br /&gt;&amp;rarr; 해결책: &lt;b&gt;TCP 윈도우 크기 조절&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;902&quot; data-start=&quot;803&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;902&quot; data-start=&quot;803&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;902&quot; data-start=&quot;803&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;943&quot; data-start=&quot;909&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;(2) 수신 버퍼 (Receive Buffer)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1096&quot; data-start=&quot;944&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1003&quot; data-start=&quot;944&quot;&gt;네트워크에서 도착한 데이터는 운영체제의 **수신 버퍼(Receive Buffer)**에 먼저 저장됨&lt;/li&gt;
&lt;li data-end=&quot;1038&quot; data-start=&quot;1004&quot;&gt;애플리케이션이 필요할 때 수신 버퍼에서 데이터를 가져감&lt;/li&gt;
&lt;li data-end=&quot;1096&quot; data-start=&quot;1039&quot;&gt;애플리케이션이 데이터를 가져가지 않으면, 버퍼가 가득 차서 &lt;b&gt;추가 데이터 수신이 불가능&lt;/b&gt;해짐&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;b&gt;예제: 수신 버퍼에서 데이터를 받는 과정&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1742699155776&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;네트워크 카드(NIC)  &amp;rarr;  수신 버퍼 (운영체제)  &amp;rarr;  애플리케이션&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;b&gt;수신 버퍼가 가득 차면?&lt;/b&gt;&lt;br /&gt;&amp;rarr; 운영체제가 더 이상 패킷을 받을 수 없어서, &lt;b&gt;송신 측에 패킷을 다시 보내달라고 요청(패킷 손실, 재전송)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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-end=&quot;1313&quot; data-start=&quot;1283&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;TCP와 UDP에서 Buffer 차이&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-end=&quot;1341&quot; data-start=&quot;1314&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;(1) TCP (신뢰성 있는 전송)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1497&quot; data-start=&quot;1342&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1397&quot; data-start=&quot;1342&quot;&gt;TCP는 &lt;b&gt;송신 버퍼와 수신 버퍼를 관리하며, 손실된 패킷을 재전송&lt;/b&gt;하는 메커니즘이 있음&lt;/li&gt;
&lt;li data-end=&quot;1447&quot; data-start=&quot;1398&quot;&gt;버퍼 크기를 자동으로 조절하여 &lt;b&gt;네트워크 혼잡을 방지&lt;/b&gt; (TCP 윈도우 크기)&lt;/li&gt;
&lt;li data-end=&quot;1497&quot; data-start=&quot;1448&quot;&gt;버퍼가 부족하면 &lt;b&gt;애플리케이션이 데이터를 더 이상 송신하거나 수신할 수 없음&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;1524&quot; data-start=&quot;1499&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;(2) UDP (비신뢰성 전송)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1619&quot; data-start=&quot;1525&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1575&quot; data-start=&quot;1525&quot;&gt;UDP는 운영체제의 &lt;b&gt;수신 버퍼만 사용하며, 버퍼가 가득 차면 데이터가 손실됨&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;1619&quot; data-start=&quot;1576&quot;&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;h2 data-end=&quot;1834&quot; data-start=&quot;1816&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;버퍼 크기 조절&lt;/b&gt;&lt;/h2&gt;
&lt;p data-end=&quot;1880&quot; data-start=&quot;1835&quot; data-ke-size=&quot;size16&quot;&gt;운영체제에서는 &lt;b&gt;네트워크 버퍼 크기를 조절하여 성능을 최적화&lt;/b&gt;할 수 있습니다.&lt;/p&gt;
&lt;p data-end=&quot;1880&quot; data-start=&quot;1835&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1880&quot; data-start=&quot;1835&quot; data-ke-size=&quot;size16&quot;&gt;- 버퍼 크기 확인 (Linux)&lt;/p&gt;
&lt;pre id=&quot;code_1742699256987&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sysctl net.core.rmem_max   # 수신 버퍼 최대 크기
sysctl net.core.wmem_max   # 송신 버퍼 최대 크기&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;- 버퍼 크기 설정 (Linux)&lt;/p&gt;
&lt;pre id=&quot;code_1742699278994&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sysctl -w net.core.rmem_max=8388608  # 수신 버퍼 크기 증가 (8MB)
sysctl -w net.core.wmem_max=8388608  # 송신 버퍼 크기 증가 (8MB)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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-end=&quot;2178&quot; data-start=&quot;2157&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;버퍼 관련 성능 이슈&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2418&quot; data-start=&quot;2179&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2270&quot; data-start=&quot;2179&quot;&gt;&lt;b&gt;버퍼 크기가 너무 작으면?&lt;/b&gt;&lt;br /&gt;&amp;rarr; 네트워크가 빠를 경우, 애플리케이션이 데이터를 가져가기 전에 버퍼가 가득 차서 &lt;b&gt;패킷이 손실될 가능성 증가&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;2341&quot; data-start=&quot;2271&quot;&gt;&lt;b&gt;버퍼 크기가 너무 크면?&lt;/b&gt;&lt;br /&gt;&amp;rarr; 메모리를 불필요하게 많이 사용하고, &lt;b&gt;응답 시간이 지연될 가능성&lt;/b&gt;이 있음&lt;/li&gt;
&lt;li data-end=&quot;2418&quot; data-start=&quot;2342&quot;&gt;&lt;b&gt;최적의 버퍼 크기 설정이 중요&lt;/b&gt;&lt;br /&gt;&amp;rarr; &lt;b&gt;애플리케이션 특성, 네트워크 속도, 패킷 손실률&lt;/b&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;h2 data-end=&quot;139&quot; data-start=&quot;109&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt; macOS의 네트워크 버퍼 관리 특징&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-end=&quot;169&quot; data-start=&quot;140&quot; data-ke-size=&quot;size23&quot;&gt;✅ &lt;b&gt;자동 튜닝 (Auto-tuning)&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;349&quot; data-start=&quot;170&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;248&quot; data-start=&quot;170&quot;&gt;macOS는 TCP의 **윈도우 크기(TCP Window Size)**와 &lt;b&gt;버퍼 크기&lt;/b&gt;를 자동으로 조절하여 네트워크 성능을 최적화함.&lt;/li&gt;
&lt;li data-end=&quot;309&quot; data-start=&quot;249&quot;&gt;네트워크 속도, 패킷 손실률, CPU 사용량 등을 고려하여 운영체제가 &lt;b&gt;버퍼 크기를 동적으로 조절&lt;/b&gt;.&lt;/li&gt;
&lt;li data-end=&quot;349&quot; data-start=&quot;310&quot;&gt;대부분의 일반적인 사용자는 버퍼 크기를 수동으로 조절할 필요 없음.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;386&quot; data-start=&quot;351&quot; 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-end=&quot;630&quot; data-start=&quot;387&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;458&quot; data-start=&quot;387&quot;&gt;&lt;b&gt;고속 네트워크 환경에서 성능이 제한됨&lt;/b&gt;&lt;br /&gt;(예: 10Gbps 이상의 네트워크에서 충분한 성능이 나오지 않는 경우)&lt;/li&gt;
&lt;li data-end=&quot;545&quot; data-start=&quot;459&quot;&gt;&lt;b&gt;대용량 파일 전송 시 속도가 기대보다 낮을 수 있음&lt;/b&gt;&lt;br /&gt;(버퍼 크기가 너무 작게 설정되면 네트워크 대역폭을 충분히 활용하지 못할 수도 있음)&lt;/li&gt;
&lt;li data-end=&quot;630&quot; data-start=&quot;546&quot;&gt;&lt;b&gt;실시간 스트리밍, VoIP(인터넷 전화)에서 지연 발생 가능&lt;/b&gt;&lt;br /&gt;(UDP 사용 시 버퍼 부족으로 인해 패킷 손실이 발생할 가능성이 있음)&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-end=&quot;2437&quot; data-start=&quot;2425&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2718&quot; data-start=&quot;2438&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2497&quot; data-start=&quot;2438&quot;&gt;**버퍼(Buffer)**는 네트워크 데이터를 운영체제와 애플리케이션 간 &lt;b&gt;임시 저장&lt;/b&gt;하는 공간&lt;/li&gt;
&lt;li data-end=&quot;2556&quot; data-start=&quot;2498&quot;&gt;&lt;b&gt;송신 버퍼(Send Buffer)&lt;/b&gt;: 애플리케이션이 보낸 데이터를 저장 후, 네트워크로 전송&lt;/li&gt;
&lt;li data-end=&quot;2620&quot; data-start=&quot;2557&quot;&gt;&lt;b&gt;수신 버퍼(Receive Buffer)&lt;/b&gt;: 네트워크에서 받은 데이터를 저장 후, 애플리케이션으로 전달&lt;/li&gt;
&lt;li data-end=&quot;2683&quot; data-start=&quot;2621&quot;&gt;&lt;b&gt;TCP는 자동 버퍼 조절 및 재전송을 지원&lt;/b&gt;, &lt;b&gt;UDP는 버퍼 크기가 고정되어 손실 발생 가능&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;2718&quot; data-start=&quot;2684&quot;&gt;&lt;b&gt;버퍼 크기 조절을 통해 성능을 최적화할 수 있음&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>programming</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/245</guid>
      <comments>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%97%90%EC%84%9C-Buffer%EB%9E%80#entry245comment</comments>
      <pubDate>Sun, 23 Mar 2025 12:10:47 +0900</pubDate>
    </item>
    <item>
      <title>랭체인과 database로 RAG 구현하기</title>
      <link>https://hmk1022.tistory.com/entry/%EB%9E%AD%EC%B2%B4%EC%9D%B8%EA%B3%BC-database%EB%A1%9C-RAG-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
      <description>&lt;h1&gt;&lt;span&gt;LangChain과&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Pinecone으로 구&lt;/span&gt;&lt;span&gt;현하는 RAG 패턴&lt;/span&gt;&lt;/h1&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;LangChain과 Pin&lt;/span&gt;&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;econe을 사용하여 RA&lt;/span&gt;&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;G 패턴을 구현하는&lt;/span&gt;&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;방법에 대해 알아보&lt;/span&gt;&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;겠습니다. &lt;br /&gt;RA&lt;/span&gt;&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;G는 대규모 언어&lt;/span&gt;&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;모델(LLM)의&lt;/span&gt;&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;응답을 더욱 정확&lt;/span&gt;&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;하고 신뢰성&lt;/span&gt;&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;&amp;nbsp;있게 만들어&lt;/span&gt;&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;주는 핵심 패&lt;/span&gt;&lt;span style=&quot;color: #333333; font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;턴입니다.&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;1. 데이터 준비 및&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;임베딩 단계&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;먼저 데이터를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;벡터 형태로 변&lt;/span&gt;&lt;span&gt;환하여 저장하&lt;/span&gt;&lt;span&gt;는 과정이 필요합니&lt;/span&gt;&lt;span&gt;다.&lt;br /&gt;&lt;br /&gt;&lt;span&gt;이&lt;/span&gt;&lt;span&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;&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;span&gt;OpenAI&lt;/span&gt;&lt;span&gt;의 임베딩 모델을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;초기화하여 텍스트를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&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;span&gt;Pinecone&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;벡터 스토어를 설&lt;/span&gt;&lt;span&gt;정하여 벡터화&lt;/span&gt;&lt;span&gt;된 데이터를 저장할&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;공간을 마련합니다&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-origin-width=&quot;1280&quot; data-origin-height=&quot;442&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvd7uE/btsMjpNq4n9/ZW8poyzqMLck2b4sL9eMx1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvd7uE/btsMjpNq4n9/ZW8poyzqMLck2b4sL9eMx1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvd7uE/btsMjpNq4n9/ZW8poyzqMLck2b4sL9eMx1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbvd7uE%2FbtsMjpNq4n9%2FZW8poyzqMLck2b4sL9eMx1%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;1280&quot; height=&quot;442&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;442&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739602074500&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# OpenAI의 임베딩 모델 초기화
embeddings = OpenAIEmbeddings(openai_api_key=os.getenv(&quot;OPENAI_API_KEY&quot;))

# Pinecone 벡터 저장소 초기화
vectorstore = PineconeVectorStore(
    index_name=os.getenv(&quot;INDEX_NAME&quot;), 
    embedding=embeddings&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;2. 검색 단계&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;span&gt;&amp;nbsp;&lt;/span&gt;관련 정보를 검&lt;/span&gt;&lt;span&gt;색하는 단계입니다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&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/bmhPr9/btsMjfEcXgp/JR4PQ9cthlCcJc2erbsKo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmhPr9/btsMjfEcXgp/JR4PQ9cthlCcJc2erbsKo1/img.png&quot; width=&quot;904&quot; height=&quot;422&quot; data-is-animation=&quot;false&quot; data-origin-height=&quot;1304&quot; data-origin-width=&quot;2796&quot; style=&quot;width: 54.0376%; margin-right: 10px;&quot; data-widthpercent=&quot;54.67&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmhPr9/btsMjfEcXgp/JR4PQ9cthlCcJc2erbsKo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmhPr9%2FbtsMjfEcXgp%2FJR4PQ9cthlCcJc2erbsKo1%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;2796&quot; height=&quot;1304&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9PjWg/btsMkX2Wxhb/o0kjdiJ0FuhcUWhIJzU930/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9PjWg/btsMkX2Wxhb/o0kjdiJ0FuhcUWhIJzU930/img.png&quot; data-origin-width=&quot;2414&quot; data-origin-height=&quot;1358&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;45.33&quot; style=&quot;width: 44.7996%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9PjWg/btsMkX2Wxhb/o0kjdiJ0FuhcUWhIJzU930/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9PjWg%2FbtsMkX2Wxhb%2Fo0kjdiJ0FuhcUWhIJzU930%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;2414&quot; height=&quot;1358&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&gt;&lt;br /&gt;&lt;br /&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;사용자의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&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;span&gt;Pinecone에&lt;/span&gt;&lt;span&gt;서 유사도 기반으&lt;/span&gt;&lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739602113361&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 벡터 스토어의 검색 기능 초기화
retriever = vectorstore.as_retriever()

# 검색 체인 생성
retrieval_chain = create_retrieval_chain(
    retriever=retriever,
    combine_docs_chain=combine_docs_chain
)&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;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;3. 문서 처리&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&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;들을 처리하고 결&lt;/span&gt;&lt;span&gt;합하는 단계입니다&lt;/span&gt;&lt;span&gt;.&lt;br /&gt;&lt;span&gt;이 단&lt;/span&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;검색&lt;/span&gt;&lt;span&gt;된 여러 문서들&lt;/span&gt;&lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&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;span&gt;결합된 문서&lt;/span&gt;&lt;span&gt;를 LLM이 이&lt;/span&gt;&lt;span&gt;해할 수 있는 형&lt;/span&gt;&lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739602147442&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;def format_docs(docs):
    return &quot;\n\n&quot;.join(doc.page_content for doc in docs)

# 문서 결합 체인 생성
combine_docs_chain = create_stuff_documents_chain(llm, retrieval_qa_chat_prompt)&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;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;4. 응답&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;생성 단계&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;LLM을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;사용하여 최종 응&lt;/span&gt;&lt;span&gt;답을 생성하는 단계&lt;/span&gt;&lt;span&gt;입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;검색된 데이터 기반으로 프롬프트에 추가해 LLM에 다시한번 검색후 근거에 있는 답변을 받고 사람에게 익숙한 자연어 처리를 수행합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2774&quot; data-origin-height=&quot;1354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oOJnY/btsMi3KADlu/TaYxk6AN3RC4WKhTXev36k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oOJnY/btsMi3KADlu/TaYxk6AN3RC4WKhTXev36k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oOJnY/btsMi3KADlu/TaYxk6AN3RC4WKhTXev36k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoOJnY%2FbtsMi3KADlu%2FTaYxk6AN3RC4WKhTXev36k%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;2774&quot; height=&quot;1354&quot; data-origin-width=&quot;2774&quot; data-origin-height=&quot;1354&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;검색된 문서&lt;/span&gt;&lt;span&gt;와 사용자의 질문을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;포함한 프롬프트를&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&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;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&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;span&gt;LLM이&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;검색된 문서를 기&lt;/span&gt;&lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&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;span&gt;응답을 지&lt;/span&gt;&lt;span&gt;정된 형식(3문장 이내&lt;/span&gt;&lt;span&gt;, 감사 인사 포함&lt;/span&gt;&lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739602181659&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;template = &quot;&quot;&quot;
Use the following pieces of retrieved context to answer the question at the end.
If you don't know the answer, just say that you don't know. don't try to make up an answer.
Use three sentence maximum and keep the answer concise as possible.
Always say &quot;thank for your asking&quot; at the end of the answer.

{context}

Question: {question}

Helpful Answer:
&quot;&quot;&quot;

custom_rag_prompt = PromptTemplate.from_template(template)

rag_chain = (
    {&quot;context&quot;: vectorstore.as_retriever() | format_docs, &quot;question&quot;: RunnablePassthrough()}
    | custom_rag_prompt
    | llm
    | StrOutputParser()
)&lt;/code&gt;&lt;/pre&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;span&gt;결론&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;RAG&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;패턴은 LL&lt;/span&gt;&lt;span&gt;M의 한계를 보&lt;/span&gt;&lt;span&gt;완하고 더 신&lt;/span&gt;&lt;span&gt;뢰할 수 있는&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;응답을 생성하는 강&lt;/span&gt;&lt;span&gt;력한 방법입니다. L&lt;/span&gt;&lt;span&gt;angChain과 Pinecone을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;사용하면 이러&lt;/span&gt;&lt;span&gt;한 RAG 패턴&lt;/span&gt;&lt;span&gt;을 쉽게 구현할&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;수 있으며, 특&lt;/span&gt;&lt;span&gt;히:&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&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;span&gt;벡터 데&lt;/span&gt;&lt;span&gt;이터베이스를 통&lt;/span&gt;&lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&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;span&gt;관&lt;/span&gt;&lt;span&gt;련 문서 기반의&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&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;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;커스터마이&lt;/span&gt;&lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;등의 장점을&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;활용할 수&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;있습니다. &lt;/span&gt;&lt;span&gt;이상으로 RAG&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;패턴 구현에 대&lt;/span&gt;&lt;span&gt;한 설명을 마치&lt;/span&gt;&lt;span&gt;겠습니다. 실&lt;/span&gt;&lt;span&gt;제 프로젝트에&lt;/span&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;적용하실 때 참&lt;/span&gt;&lt;span&gt;고가 되셨기&lt;/span&gt;&lt;span&gt;를 바랍니다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;</description>
      <category>AI</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/244</guid>
      <comments>https://hmk1022.tistory.com/entry/%EB%9E%AD%EC%B2%B4%EC%9D%B8%EA%B3%BC-database%EB%A1%9C-RAG-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0#entry244comment</comments>
      <pubDate>Sat, 15 Feb 2025 15:37:06 +0900</pubDate>
    </item>
    <item>
      <title>쿠버네티스 pod</title>
      <link>https://hmk1022.tistory.com/entry/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-pod</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Pod&lt;/b&gt;: 쿠버네티스에서 가장 작은 실행 단위&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠버네티스에서 &lt;b&gt;Pod&lt;/b&gt;는 &lt;b&gt;애플리케이션을 실행하는 가장 작은 단위&lt;/b&gt;입니다. 하지만 여기서 중요한 점은 &lt;b&gt;Pod 하나에는 하나 이상의 컨테이너가 있을 수 있다&lt;/b&gt;는 것입니다. 마치 &lt;b&gt;하나의 집&lt;/b&gt; 안에 여러 사람이 살 수 있는 것처럼, &lt;b&gt;Pod&lt;/b&gt; 안에 여러 개의 컨테이너가 함께 살 수 있습니다.&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;b&gt;집&lt;/b&gt;을 하나 짓는다고 했을 때, 이 집 안에 &lt;b&gt;여러 명의 사람들이 함께 살 수 있습니다.&lt;/b&gt; 집을 짓는 것이 &lt;b&gt;Pod&lt;/b&gt;이고, 그 안에서 함께 사는 사람들이 바로 &lt;b&gt;컨테이너&lt;/b&gt;라고 할 수 있습니다. 집을 하나 짓는 데 있어 &lt;b&gt;Pod&lt;/b&gt;는 &lt;b&gt;여러 개의 컨테이너가 함께 묶여서 동작하는 공간&lt;/b&gt;인 셈이죠.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;296&quot; data-origin-height=&quot;170&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIGmHl/btsL2RDNes9/LrCikSs7gHK2l9vrkW4v50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIGmHl/btsL2RDNes9/LrCikSs7gHK2l9vrkW4v50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIGmHl/btsL2RDNes9/LrCikSs7gHK2l9vrkW4v50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIGmHl%2FbtsL2RDNes9%2FLrCikSs7gHK2l9vrkW4v50%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;230&quot; data-origin-width=&quot;296&quot; data-origin-height=&quot;170&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Pod의 구조&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Pod&lt;/b&gt;는 &lt;b&gt;컨테이너들의 집합&lt;/b&gt;입니다. 일반적으로 &lt;b&gt;Pod&lt;/b&gt;에는 하나의 컨테이너만 들어 있지만, &lt;b&gt;여러 개의 컨테이너&lt;/b&gt;가 함께 있어야 할 때도 있습니다. 예를 들어, 서로 긴밀히 상호작용하는 두 애플리케이션이 하나의 &lt;b&gt;Pod&lt;/b&gt; 안에서 실행될 수 있습니다. 이러한 상황은 &lt;b&gt;Sidecar 패턴&lt;/b&gt;으로 자주 사용됩니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1178&quot; data-origin-height=&quot;491&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ax6fO/btsL3AoaL1K/1kA1qs9SeKrSPuNKhEXGqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ax6fO/btsL3AoaL1K/1kA1qs9SeKrSPuNKhEXGqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ax6fO/btsL3AoaL1K/1kA1qs9SeKrSPuNKhEXGqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAx6fO%2FbtsL3AoaL1K%2F1kA1qs9SeKrSPuNKhEXGqK%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;1178&quot; height=&quot;491&quot; data-origin-width=&quot;1178&quot; data-origin-height=&quot;491&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Pod 안의 여러 컨테이너&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;컨테이너 1&lt;/b&gt;: 하나의 애플리케이션을 실행하는 컨테이너&lt;/li&gt;
&lt;li&gt;&lt;b&gt;컨테이너 2&lt;/b&gt;: 그 애플리케이션에 필요한 보조 작업을 하는 컨테이너 (예: 로그 수집, 데이터 처리 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 컨테이너들은 &lt;b&gt;Pod 안에서 자원(CPU, 메모리 등)을 공유&lt;/b&gt;하며 함께 동작합니다. 두 컨테이너가 &lt;b&gt;상호작용&lt;/b&gt;해야 하기 때문에 &lt;b&gt;Pod&lt;/b&gt; 안에 함께 배치된 것이죠.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Pod의 특징&lt;br /&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;1400&quot; data-origin-height=&quot;762&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/de3AZ5/btsL4rD8qn9/H6n1LSKLgc3kMlFdnhkJb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/de3AZ5/btsL4rD8qn9/H6n1LSKLgc3kMlFdnhkJb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/de3AZ5/btsL4rD8qn9/H6n1LSKLgc3kMlFdnhkJb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fde3AZ5%2FbtsL4rD8qn9%2FH6n1LSKLgc3kMlFdnhkJb0%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;687&quot; height=&quot;374&quot; data-origin-width=&quot;1400&quot; data-origin-height=&quot;762&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;같은 네트워크 공간을 공유&lt;/b&gt;: Pod 안의 모든 컨테이너는 &lt;b&gt;같은 IP 주소&lt;/b&gt;를 공유하며, 서로 &lt;b&gt;localhost&lt;/b&gt;처럼 통신할 수 있습니다. 마치 &lt;b&gt;같은 집에 살고 있는 사람들이 같은 집 주소를 공유&lt;/b&gt;하는 것과 같죠. 그래서 같은 Pod 안의 컨테이너들은 &lt;b&gt;서로 쉽게 통신&lt;/b&gt;할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공유 스토리지&lt;/b&gt;: Pod 안의 여러 컨테이너는 &lt;b&gt;공유 디스크&lt;/b&gt;를 사용할 수 있습니다. 예를 들어, 여러 컨테이너가 동일한 데이터를 저장하고 읽어야 할 때, Pod는 &lt;b&gt;공유 스토리지&lt;/b&gt;를 제공합니다. 이는 마치 집 안에 있는 여러 사람이 &lt;b&gt;같은 책상이나 서랍을 공유&lt;/b&gt;하는 것처럼, 데이터를 공유하는 방식입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;생애주기 관리&lt;/b&gt;: Pod는 &lt;b&gt;하나의 생애주기&lt;/b&gt;를 가집니다. 즉, Pod가 생성되면 &lt;b&gt;하나의 단위로 실행&lt;/b&gt;, &lt;b&gt;종료&lt;/b&gt;, &lt;b&gt;삭제&lt;/b&gt;됩니다. Pod 내부에서 실행되는 &lt;b&gt;컨테이너&lt;/b&gt;들도 이와 동일하게 &lt;b&gt;같은 생애주기를 가집니다&lt;/b&gt;. 이는 마치 &lt;b&gt;하나의 집이 만들어지고, 사람이 들어가 살고, 집이 없어지는 것&lt;/b&gt;과 같습니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Pod의 예시&lt;/b&gt;&lt;/h3&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;b&gt;Pod&lt;/b&gt;를 예시로 들어보겠습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Pod&lt;/b&gt; 안에는 &lt;b&gt;웹 서버&lt;/b&gt;를 실행하는 컨테이너가 하나 있을 수 있습니다. 이 컨테이너는 실제로 웹 애플리케이션의 로직을 처리하고 사용자 요청을 받습니다.&lt;/li&gt;
&lt;li&gt;또 다른 &lt;b&gt;컨테이너&lt;/b&gt;는 로그를 수집하거나, 캐시 서버로서 웹 서버와 통신하는 역할을 할 수 있습니다. 이 두 컨테이너는 &lt;b&gt;같은 IP&lt;/b&gt;와 &lt;b&gt;같은 네트워크 공간&lt;/b&gt;을 공유하면서 협력합니다.&lt;br /&gt;&lt;br /&gt;&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;Pod 생성과 관리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠버네티스에서 Pod는 &lt;b&gt;배포 설정&lt;/b&gt;을 통해 관리됩니다. 예를 들어, 웹 애플리케이션이 잘 실행되도록 여러 Pod를 동시에 실행해야 할 때는 &lt;b&gt;ReplicaSet&lt;/b&gt;을 사용하여 여러 개의 동일한 Pod를 배치하고, 자동으로 &lt;b&gt;Pod의 상태를 관리&lt;/b&gt;합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Pod 생성&lt;/b&gt;: 쿠버네티스는 kubectl 명령어를 사용해 Pod을 생성할 수 있습니다.위 명령어는 my-image 이미지를 기반으로 my-pod라는 이름의 Pod을 생성합니다.
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;kubectl run my-pod --image=my-image&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;
&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Pod 관리&lt;/b&gt;: Pod의 상태를 확인하거나 삭제할 수도 있습니다.
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;span&gt;kubectl get pods &lt;span&gt;# Pod 상태 확인&lt;/span&gt; kubectl delete pod my-pod &lt;span&gt;# Pod 삭제&lt;/span&gt; &lt;/span&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Pod이 중요한 이유&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Pod&lt;/b&gt;는 &lt;b&gt;애플리케이션을 실행하는 가장 작은 단위&lt;/b&gt;이기 때문에, 쿠버네티스의 &lt;b&gt;핵심&lt;/b&gt;이라고 할 수 있습니다. 그럼에도 불구하고 &lt;b&gt;Pod 자체는 독립적으로 실행되지 않으며&lt;/b&gt;, 쿠버네티스의 &lt;b&gt;다양한 리소스들과 협력&lt;/b&gt;하여 애플리케이션을 &lt;b&gt;효율적이고 안정적으로 운영&lt;/b&gt;할 수 있습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;확장성&lt;/b&gt;: 여러 Pod을 만들어서 애플리케이션을 &lt;b&gt;수평 확장&lt;/b&gt;할 수 있습니다. 예를 들어, 사용자가 많아지면 &lt;b&gt;Pod&lt;/b&gt;를 더 추가해서 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;복원력&lt;/b&gt;: Pod이 실패하거나 장애가 발생하면, 쿠버네티스는 자동으로 새로운 Pod을 생성하여 애플리케이션을 &lt;b&gt;복구&lt;/b&gt;합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;Pod과 마스터노드 워커노드&lt;br /&gt;&lt;/b&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;890&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmPYtV/btsL3w0o0FF/nD4izB1fZAgPVcfrbpPkpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmPYtV/btsL3w0o0FF/nD4izB1fZAgPVcfrbpPkpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmPYtV/btsL3w0o0FF/nD4izB1fZAgPVcfrbpPkpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmPYtV%2FbtsL3w0o0FF%2FnD4izB1fZAgPVcfrbpPkpK%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;890&quot; height=&quot;630&quot; data-origin-width=&quot;890&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마스터 노드, 노드, 그리고 Pod이 분리된 이유는 &lt;b&gt;각각의 역할&lt;/b&gt;과 &lt;b&gt;책임&lt;/b&gt;을 명확히 하여 &lt;b&gt;쿠버네티스의 확장성&lt;/b&gt;과 &lt;b&gt;유지 보수성&lt;/b&gt;을 극대화하기 위해서입니다. 각 개념을 &lt;b&gt;간단히 설명&lt;/b&gt;하고, 그들이 분리된 이유를 이해하기 쉽게 풀어보겠습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. &lt;b&gt;마스터 노드&lt;/b&gt; (Control Plane)&lt;/h3&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;b&gt;중앙 관리 시스템&lt;/b&gt;입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;책임&lt;/b&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;b&gt;스케줄링&lt;/b&gt;: Pod이 &lt;b&gt;어떤 노드&lt;/b&gt;에서 실행될지 결정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;컨트롤러 관리&lt;/b&gt;: Pod의 상태를 모니터링하고, 필요 시 재시작하거나 복원합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;API 서버&lt;/b&gt; 제공: 사용자가 &lt;b&gt;kubectl&lt;/b&gt; 명령어를 통해 클러스터와 상호작용할 수 있도록 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마스터 노드는 &lt;b&gt;노드나 Pod을 관리하는 역할&lt;/b&gt;을 하며, &lt;b&gt;애플리케이션 실행을 담당하지 않습니다&lt;/b&gt;. 마스터 노드가 없다면, &lt;b&gt;클러스터를 관리&lt;/b&gt;할 방법이 없어지므로 클러스터가 제대로 작동하지 않게 됩니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. &lt;b&gt;워커 노드&lt;/b&gt; (Worker Node)&lt;/h3&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;b&gt;Pod&lt;/b&gt;를 실행하는 서버입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;책임&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 &lt;b&gt;Pod&lt;/b&gt;가 실행되는 &lt;b&gt;환경&lt;/b&gt;을 제공합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Kubelet&lt;/b&gt;: Pod을 관리하고, 클러스터의 상태를 마스터 노드에 보고합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;컨테이너 실행&lt;/b&gt;: Pod 내의 컨테이너를 실행합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자원 관리&lt;/b&gt;: CPU, 메모리, 네트워크 등을 관리하여 Pod이 실행되는 데 필요한 자원을 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;워커 노드가 없으면&lt;/b&gt; 애플리케이션을 실행할 수 없고, 쿠버네티스가 제공하는 &lt;b&gt;배포, 확장, 장애 복구&lt;/b&gt; 등의 기능을 사용할 수 없습니다. 즉, &lt;b&gt;애플리케이션을 실행하는 노드는 반드시 필요&lt;/b&gt;합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. &lt;b&gt;Pod&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;b&gt;역할&lt;/b&gt;: &lt;b&gt;애플리케이션의 실행 단위&lt;/b&gt;입니다. 하나 이상의 컨테이너를 포함할 수 있으며, 같은 네트워크 및 저장소를 공유합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;책임&lt;/b&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;: Pod 내의 여러 컨테이너는 같은 네트워크를 공유하고, 동일한 자원을 사용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;애플리케이션 실행&lt;/b&gt;: 실제로 실행되는 애플리케이션의 환경을 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pod은 &lt;b&gt;하나 이상의 컨테이너&lt;/b&gt;를 &lt;b&gt;같은 네트워크 환경에서 묶어&lt;/b&gt; 실행하기 위한 &lt;b&gt;기본 단위&lt;/b&gt;입니다. &lt;b&gt;Pod이 없으면&lt;/b&gt; 실제 애플리케이션을 실행할 수 없기 때문에, Pod이 반드시 필요합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;결론&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠버네티스에서 &lt;b&gt;Pod&lt;/b&gt;는 애플리케이션을 실행하는 &lt;b&gt;가장 작은 단위&lt;/b&gt;이자, &lt;b&gt;여러 개의 컨테이너&lt;/b&gt;가 하나로 묶여 있는 &lt;b&gt;그릇&lt;/b&gt;입니다. Pod 안의 컨테이너들은 &lt;b&gt;네트워크와 스토리지를 공유&lt;/b&gt;하며 협력하여 애플리케이션을 실행합니다. 이는 마치 &lt;b&gt;하나의 집에 여러 사람이 함께 살고 협력하는&lt;/b&gt; 구조와 비슷합니다. 쿠버네티스에서 Pod은 &lt;b&gt;중요한 단위로&lt;/b&gt;, 애플리케이션을 관리하고 운영하는 데 핵심적인 역할을 합니다.&lt;/p&gt;</description>
      <category>CI&amp;amp;CD</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/243</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-pod#entry243comment</comments>
      <pubDate>Sun, 2 Feb 2025 22:25:06 +0900</pubDate>
    </item>
    <item>
      <title>쿠버네티스 아키텍처 마스터 &amp;amp; 워커 노드 관리방식</title>
      <link>https://hmk1022.tistory.com/entry/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EB%A7%88%EC%8A%A4%ED%84%B0-%EC%9B%8C%EC%BB%A4-%EB%85%B8%EB%93%9C-%EA%B4%80%EB%A6%AC%EB%B0%A9%EC%8B%9D</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;쿠버네티스 아키텍처: 마스터 노드와 워커 노드 관리 방식&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠버네티스(Kubernetes)는 &lt;b&gt;애플리케이션을 자동으로 관리하고 조정하는 시스템&lt;/b&gt;입니다. 큰 기업에서 수백, 수천 대의 서버를 관리할 때, 사람 손으로 하나하나 모든 것을 조정하는 것은 매우 어려운 일이죠. 그래서 쿠버네티스가 등장하여, 여러 서버를 효율적으로 관리하고 애플리케이션을 원활하게 실행할 수 있도록 도와줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 중요한 역할을 하는 두 가지가 &lt;b&gt;마스터 노드(Master Node)&lt;/b&gt;와 &lt;b&gt;워커 노드(Worker Node)&lt;/b&gt;입니다. 이를 쉽게 이해할 수 있도록, 마치 &lt;b&gt;회사의 부서&lt;/b&gt;와 비슷한 구조로 설명해 보겠습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;451&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mASmU/btsL4AnrIV8/TXkWJeC4jmEkxMZMOQmbe1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mASmU/btsL4AnrIV8/TXkWJeC4jmEkxMZMOQmbe1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mASmU/btsL4AnrIV8/TXkWJeC4jmEkxMZMOQmbe1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmASmU%2FbtsL4AnrIV8%2FTXkWJeC4jmEkxMZMOQmbe1%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;700&quot; height=&quot;451&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;451&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마스터 노드(Master Node)&lt;/b&gt;: 회사의 관리자&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마스터 노드는 쿠버네티스의 &lt;b&gt;중앙 관리 시스템&lt;/b&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;API Server (kube-apiserver)&lt;/b&gt;: 마스터 노드는 회사의 &lt;b&gt;관리자&lt;/b&gt;가 다양한 부서와 소통하는 창구와 같습니다. 예를 들어, 회사의 직원들이 요청을 하면, 관리자(API Server)가 이를 받아 적절히 처리합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Scheduler (kube-scheduler)&lt;/b&gt;: 마스터 노드의 &lt;b&gt;스케줄러&lt;/b&gt;는 각 부서에 일을 할당하는 역할을 합니다. 예를 들어, 오늘 중요한 프로젝트가 있다면, &quot;이 일을 누구에게 맡길지?&quot;를 결정하는 사람이 바로 스케줄러입니다. 마스터 노드는 어떤 일을 할지, 그 일을 누가 할지 결정합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Controller Manager (kube-controller-manager)&lt;/b&gt;: 마스터 노드는 회사의 상태를 &lt;b&gt;모니터링&lt;/b&gt;하고, &lt;b&gt;필요한 변화&lt;/b&gt;를 일으킵니다. 예를 들어, 부서에 사람이 부족하면 이를 채워주는 역할을 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;etcd&lt;/b&gt;: 마스터 노드는 회사의 &lt;b&gt;중요한 기록&lt;/b&gt;을 보관합니다. 모든 회의록, 회의에서 나온 결정을 &lt;b&gt;보관하는 서류철&lt;/b&gt; 같은 역할을 합니다. 그래서 언제든지 이 정보를 참고할 수 있게 되죠.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 마스터 노드는 회사에서 &lt;b&gt;모든 일의 방향을 결정하고&lt;/b&gt;, 각 부서(워커 노드)가 해야 할 일을 &lt;b&gt;배치&lt;/b&gt;하는 역할을 합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;워커 노드(Worker Node)&lt;/b&gt;: 회사의 실무자들&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;워커 노드는 회사의 &lt;b&gt;실제 업무를 수행하는 부서들&lt;/b&gt;입니다. 마스터 노드에서 결정된 일들을 실제로 &lt;b&gt;실행&lt;/b&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;Kubelet&lt;/b&gt;: 워커 노드는 마치 부서의 &lt;b&gt;팀장&lt;/b&gt; 같은 존재입니다. 팀장은 마스터 노드에서 주어진 업무를 각 팀원에게 분배하고, 업무가 잘 진행되는지 점검합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Kube Proxy&lt;/b&gt;: 부서 내에서 &lt;b&gt;협업&lt;/b&gt;을 원활하게 해주는 시스템입니다. 예를 들어, 마케팅 부서와 개발 부서가 함께 일을 할 때, 각 부서 간에 어떻게 일을 나누고 조율할지 책임지는 역할입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;컨테이너 런타임&lt;/b&gt;: 워커 노드는 &lt;b&gt;실제 업무를 처리하는 장비&lt;/b&gt;처럼, 업무를 실제로 처리하는 시스템입니다. 예를 들어, 컴퓨터나 전화, 소프트웨어 등이 이에 해당합니다. 이 시스템이 실제로 실행되는 곳이 바로 워커 노드입니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 워커 노드는 마스터 노드가 주는 지시를 받고, 실제로 애플리케이션을 실행하고 결과를 만들어내는 &lt;b&gt;작업자들&lt;/b&gt;입니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마스터 노드와 워커 노드의 협력&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;890&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmK1nU/btsL4za0wFk/VSkdKeichCKkG5TiXfUtJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmK1nU/btsL4za0wFk/VSkdKeichCKkG5TiXfUtJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmK1nU/btsL4za0wFk/VSkdKeichCKkG5TiXfUtJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmK1nU%2FbtsL4za0wFk%2FVSkdKeichCKkG5TiXfUtJ0%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;890&quot; height=&quot;630&quot; data-origin-width=&quot;890&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 마스터 노드와 워커 노드가 어떻게 협력하는지 예를 들어 보겠습니다. 상상해 보세요, 마스터 노드는 회사의 &lt;b&gt;관리자&lt;/b&gt;이고, 워커 노드는 &lt;b&gt;각 부서의 실무자들&lt;/b&gt;입니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;파드 배치&lt;/b&gt;: 마스터 노드(관리자)가 새로운 업무를 할당합니다. 예를 들어, &quot;마케팅 부서에 광고 캠페인을 맡겨라&quot;고 지시하면, 마케팅 부서(워커 노드)는 이를 실행합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상태 관리&lt;/b&gt;: 마스터 노드는 각 부서가 제대로 일을 하고 있는지 모니터링합니다. 예를 들어, &quot;마케팅 부서에서 광고 캠페인을 시작했다. 그런데 문제가 발생했을 때 어떻게 대처할지?&quot;를 관리합니다. 만약 부서에서 일이 잘 안 되면, 마스터 노드는 수정할 방법을 제시하고 이를 해결하려 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;실행과 조정&lt;/b&gt;: 마스터 노드는 일을 계획하고, 워커 노드는 그 계획을 실행합니다. 만약 마케팅 부서에 사람이 부족하면, 마스터 노드는 그 문제를 해결할 방법을 제시합니다. 각 부서는 마스터 노드의 지시에 맞춰서 업무를 수행합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;고가용성(High Availability)&lt;/b&gt;: 두 가지가 함께 있어야 안정적&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠버네티스에서는 &lt;b&gt;마스터 노드&lt;/b&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;마스터 노드&lt;/b&gt;가 하나만 있으면 문제가 생길 수 있기 때문에, 여러 대의 마스터 노드를 두어 **고가용성(HA)**을 보장할 수 있습니다. 만약 하나의 마스터 노드가 실패해도, 다른 마스터 노드가 계속 클러스터를 관리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;워커 노드&lt;/b&gt;도 여러 대로 분산시켜서, 한 대의 워커 노드가 문제가 생기면 다른 워커 노드가 대신 업무를 처리할 수 있도록 합니다. 이렇게 여러 대의 노드를 통해 &lt;b&gt;부하 분산&lt;/b&gt;을 할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결론&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿠버네티스에서 &lt;b&gt;마스터 노드&lt;/b&gt;는 &lt;b&gt;회사 관리자&lt;/b&gt;처럼 클러스터의 상태를 관리하고 조정하며, &lt;b&gt;워커 노드&lt;/b&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;b&gt;마스터 노드&lt;/b&gt;와 &lt;b&gt;워커 노드&lt;/b&gt;입니다.&lt;/p&gt;</description>
      <category>CI&amp;amp;CD</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/242</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98-%EB%A7%88%EC%8A%A4%ED%84%B0-%EC%9B%8C%EC%BB%A4-%EB%85%B8%EB%93%9C-%EA%B4%80%EB%A6%AC%EB%B0%A9%EC%8B%9D#entry242comment</comments>
      <pubDate>Sun, 2 Feb 2025 21:21:19 +0900</pubDate>
    </item>
    <item>
      <title>컨테이너와 오케스트레이션 쉽게 이해하기</title>
      <link>https://hmk1022.tistory.com/entry/%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EC%99%80-%EC%98%A4%EC%BC%80%EC%8A%A4%ED%8A%B8%EB%A0%88%EC%9D%B4%EC%85%98-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</link>
      <description>&lt;h1 data-pm-slice=&quot;0 0 []&quot;&gt;&lt;span&gt;컨테이너와 오케스트레이션: 쉽게 이해하기&lt;/span&gt;&lt;/h1&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K0Bzx/btsL4ao0iVm/YzyJK7h5l4TYDyXMDmQLT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K0Bzx/btsL4ao0iVm/YzyJK7h5l4TYDyXMDmQLT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K0Bzx/btsL4ao0iVm/YzyJK7h5l4TYDyXMDmQLT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK0Bzx%2FbtsL4ao0iVm%2FYzyJK7h5l4TYDyXMDmQLT0%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;1024&quot; height=&quot;576&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;1. 컨테이너란 무엇인가?&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;컨테이너를 도시락에 비유하면?&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;컨테이너는 애플리케이션을 실행하는 가벼운 가상화 기술이다. 쉽게 말해 &quot;애플리케이션을 실행할 수 있는 도시락&quot; 같은 개념이다.&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;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;도시락을 어디서든 꺼내면 똑같은 환경에서 바로 먹을 수 있다.&lt;/span&gt;&lt;/li&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;기존 방식과의 차이점&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구분전통적인 VM(가상 머신)컨테이너&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;span&gt;실행 속도&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;무겁고 느림&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;가볍고 빠름&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;리소스 사용&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;OS별로 많은 리소스 필요&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;최소한의 리소스 사용&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;이식성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;환경마다 설정이 다름&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;어디서든 같은 환경 유지&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;대표적인 컨테이너 기술&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;&lt;b&gt;Docker&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 가장 많이 사용되는 컨테이너 플랫폼&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Podman&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: Docker와 유사하지만, 데몬 없이 작동&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Containerd&lt;/b&gt;&lt;/span&gt;&lt;span&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;2. 컨테이너 오케스트레이션이 필요한 이유&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;컨테이너 한 개만 쓰면 괜찮은데, 여러 개가 되면?&lt;/span&gt;&lt;/h3&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;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;가게를 처음 열었을 때는 직원 1~2명이 모든 주문을 처리할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;하지만 주문이 폭주하면 직원이 더 필요하고, 주문을 자동으로 분배하는 시스템이 필요하다.&lt;/span&gt;&lt;/li&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;오케스트레이션의 필요성&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;컨테이너를 자동으로 배포하고 관리할 수 있어야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;컨테이너가 죽으면 자동으로 재시작해야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;트래픽이 많아지면 컨테이너를 자동으로 늘려야 한다.&lt;/span&gt;&lt;/li&gt;
&lt;li&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;이 역할을 하는 것이 바로 &quot;컨테이너 오케스트레이션 시스템&quot;이다.&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;3. 컨테이너 오케스트레이션이란?&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;대표적인 오케스트레이션 도구&lt;/span&gt;&lt;/h3&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;Kubernetes(쿠버네티스)&lt;/b&gt;&lt;/span&gt;&lt;span&gt; - 가장 많이 사용되는 오케스트레이션 툴&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Docker Swarm&lt;/b&gt;&lt;/span&gt;&lt;span&gt; - Docker에 내장된 오케스트레이션 기능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Amazon ECS&lt;/b&gt;&lt;/span&gt;&lt;span&gt; - AWS에서 제공하는 컨테이너 관리 서비스&lt;/span&gt;&lt;/li&gt;
&lt;/ol&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;4. 컨테이너 오케스트레이션이 해결하는 문제&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;쿠버네티스를 쓰면 좋은 점&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;자동 배포 및 롤백 기능 제공&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;장애 발생 시 컨테이너를 자동으로 재시작하는 복구 기능 지원&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;트래픽 증가에 따라 컨테이너를 자동으로 추가하는 오토스케일링 기능&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&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;5. 쿠버네티스&lt;br /&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;885&quot; data-origin-height=&quot;443&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kEOE4/btsL4ZUwObY/svNXwIs800Fr1BKKIbHqV1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kEOE4/btsL4ZUwObY/svNXwIs800Fr1BKKIbHqV1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kEOE4/btsL4ZUwObY/svNXwIs800Fr1BKKIbHqV1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkEOE4%2FbtsL4ZUwObY%2FsvNXwIs800Fr1BKKIbHqV1%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;642&quot; height=&quot;321&quot; data-origin-width=&quot;885&quot; data-origin-height=&quot;443&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&lt;span&gt;그리고 그 역할을 하는 대표적인 시스템이 바로 쿠버네티스(Kubernetes)다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;VM과 비교한 도커의 단점&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;보안 이슈&lt;/b&gt;: 도커는 호스트 OS의 커널을 공유하므로, VM처럼 격리된 환경을 제공하지 않아요. 이는 비교적 보안적으로 취약할 수 있어요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OS 종속성&lt;/b&gt;: 도커는 호스트 OS의 커널을 사용하는데, 이로 인해 일부 OS에선 제한적일 수 있어요. 예를 들어, 리눅스 기반 도커는 윈도우에서 완전히 동일하게 동작하지 않을 수 있어요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;복잡한 네트워크 관리&lt;/b&gt;: 도커 네트워크는 VM에 비해 설정이 복잡할 수 있고, 여러 컨테이너가 서로 통신할 때 복잡도가 올라갈 수 있어요.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;파일 시스템 성능&lt;/b&gt;: 도커의 파일 시스템은 VM에 비해 느릴 수 있어요, 특히 많은 파일을 읽고 쓸 때 성능 저하가 있을 수 있어요.&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>CI&amp;amp;CD</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/241</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88%EC%99%80-%EC%98%A4%EC%BC%80%EC%8A%A4%ED%8A%B8%EB%A0%88%EC%9D%B4%EC%85%98-%EC%89%BD%EA%B2%8C-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0#entry241comment</comments>
      <pubDate>Sun, 2 Feb 2025 19:05:57 +0900</pubDate>
    </item>
    <item>
      <title>LangChain으로 AI 애플리케이션</title>
      <link>https://hmk1022.tistory.com/entry/LangChain%EC%9C%BC%EB%A1%9C-AI-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근 대형 언어 모델(LLM, Large Language Model)의 발전으로 AI를 활용한 애플리케이션 개발이 활발해지고 있습니다. 하지만 단순히 OpenAI API를 호출하는 것만으로는 복잡한 애플리케이션을 만들기 어렵죠.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;LangChain&lt;/b&gt;은 이런 문제를 해결하기 위해 만들어진 &lt;b&gt;프레임워크&lt;/b&gt;로, 언어 모델을 다양한 데이터와 연결하고, 에이전트를 통해 복잡한 작업을 수행할 수 있도록 도와줍니다. 이번 글에서는 LangChain의 주요 개념과 아키텍처, 그리고 Python 코드 예제를 소개하겠습니다.&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;1200&quot; data-origin-height=&quot;628&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvUygS/btsL2BOrQ84/WVaDdWiP1L2PyQ5y9djXIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvUygS/btsL2BOrQ84/WVaDdWiP1L2PyQ5y9djXIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvUygS/btsL2BOrQ84/WVaDdWiP1L2PyQ5y9djXIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvUygS%2FbtsL2BOrQ84%2FWVaDdWiP1L2PyQ5y9djXIk%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;1200&quot; height=&quot;628&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;628&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;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️⃣ LangChain이란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LangChain은 &lt;b&gt;대형 언어 모델을 활용한 AI 애플리케이션을 쉽게 개발할 수 있도록 지원하는 프레임워크&lt;/b&gt;입니다.&lt;br /&gt;단순한 텍스트 생성뿐만 아니라 &lt;b&gt;문서 검색, API 호출, 데이터 분석&lt;/b&gt; 등 다양한 작업을 수행할 수 있도록 설계되어 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;✅ LangChain의 핵심 개념&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;LLM (Large Language Model)&lt;/b&gt; &amp;rarr; OpenAI, Hugging Face 등 다양한 언어 모델을 쉽게 연결&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Prompt Templates&lt;/b&gt; &amp;rarr; 입력 프롬프트를 템플릿화하여 관리&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Memory&lt;/b&gt; &amp;rarr; 대화 내역을 저장하여 컨텍스트 유지&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Agents&lt;/b&gt; &amp;rarr; 여러 도구(tool)를 조합해 복잡한 작업 수행&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Chains&lt;/b&gt; &amp;rarr; 여러 단계를 거치는 작업을 연결&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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️⃣ LangChain 기초: LLM 사용하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LangChain을 이용해 &lt;b&gt;간단한 텍스트 생성기&lt;/b&gt;를 만들어보겠습니다.&lt;br /&gt;아래 코드는 OpenAI의 gpt-3.5-turbo 모델을 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1738377164259&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;from langchain.llms import OpenAI

# OpenAI 모델 사용
llm = OpenAI(model_name=&quot;gpt-3.5-turbo&quot;, openai_api_key=&quot;your_api_key&quot;)

# 텍스트 생성 실행
response = llm(&quot;LangChain이 무엇인가요?&quot;)
print(response)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 LangChain을 이용하면 &lt;b&gt;간단한 코드로 LLM을 활용&lt;/b&gt;할 수 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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️⃣ LangChain의 핵심 아키텍처&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LangChain은 단순한 LLM 호출을 넘어서, &lt;b&gt;복잡한 AI 애플리케이션을 구성할 수 있는 구조&lt;/b&gt;를 제공합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  1. 체인 (Chain)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;체인은 여러 단계를 연결하는 구조입니다. 예를 들어, 질문을 받고 &amp;rarr; 검색 &amp;rarr; 요약하는 프로세스를 하나의 체인으로 구성할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1738377184761&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from langchain.chains import LLMChain
from langchain.prompts import PromptTemplate

# 프롬프트 템플릿 생성
template = PromptTemplate.from_template(&quot;한국의 수도는 어디인가요? {question}&quot;)

# LLM 체인 생성
chain = LLMChain(llm=llm, prompt=template)

# 실행
response = chain.run(&quot;서울인가요?&quot;)
print(response)&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;  2. 에이전트 (Agent)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;에이전트는 LLM이 여러 도구(tool)를 활용하여 &lt;b&gt;스스로 의사 결정을 하며 문제를 해결하는 구조&lt;/b&gt;입니다.&lt;br /&gt;예를 들어, LLM이 계산이 필요하면 &lt;b&gt;계산기 API를 호출&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;pre id=&quot;code_1738377204115&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;from langchain.agents import initialize_agent, AgentType
from langchain.agents.tools import Tool
from langchain.llms import OpenAI

# 사용할 도구 (예: 간단한 계산기)
def calculator(expression):
    return eval(expression)

calc_tool = Tool(
    name=&quot;Calculator&quot;,
    func=calculator,
    description=&quot;수학 계산을 수행하는 도구&quot;
)

# 에이전트 생성
agent = initialize_agent(
    tools=[calc_tool],
    llm=OpenAI(model_name=&quot;gpt-3.5-turbo&quot;, openai_api_key=&quot;your_api_key&quot;),
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True
)

# 실행
agent.run(&quot;10 + 25는 얼마야?&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;위 코드에서는 AI가 calculator 함수를 직접 사용하여 계산을 수행합니다.&lt;br /&gt;즉, &lt;b&gt;LLM이 직접 계산하는 것이 아니라, 필요한 작업을 적절한 도구에 위임하는 방식&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4️⃣ 실전 예제: 웹 검색을 활용한 Q&amp;amp;A 시스템&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LangChain의 에이전트를 활용하면 &lt;b&gt;실시간 정보 검색 기능&lt;/b&gt;을 추가할 수 있습니다.&lt;br /&gt;아래 코드는 SerpAPI를 사용하여 &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_1738377242979&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;from langchain.agents import initialize_agent, AgentType
from langchain.tools import SerpAPIWrapper
from langchain.llms import OpenAI

# 웹 검색 도구
search = SerpAPIWrapper(serpapi_api_key=&quot;your_serpapi_key&quot;)

# 에이전트 생성
agent = initialize_agent(
    tools=[search],
    llm=OpenAI(model_name=&quot;gpt-3.5-turbo&quot;, openai_api_key=&quot;your_api_key&quot;),
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True
)

# 실행
agent.run(&quot;오늘 서울 날씨 어때?&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 LangChain을 이용해 &lt;b&gt;LLM이 웹 검색을 수행하고 최신 정보를 반영하여 응답&lt;/b&gt;할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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️⃣ LangChain의 활용 사례&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LangChain을 사용하면 다양한 AI 애플리케이션을 개발할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;✅ &lt;b&gt;챗봇 개발&lt;/b&gt; &amp;rarr; 사용자의 질문에 답하는 대화형 AI&lt;br /&gt;✅ &lt;b&gt;문서 요약 및 분석&lt;/b&gt; &amp;rarr; 긴 문서를 요약하고 주요 내용을 추출&lt;br /&gt;✅ &lt;b&gt;자동화된 연구 도구&lt;/b&gt; &amp;rarr; 웹 검색과 요약을 통해 연구 보조&lt;br /&gt;✅ &lt;b&gt;AI 기반 데이터 분석&lt;/b&gt; &amp;rarr; AI가 데이터를 해석하고 인사이트 도출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LangChain은 LLM을 활용한 &lt;b&gt;강력한 AI 애플리케이션을 쉽게 개발할 수 있도록 도와주는 프레임워크&lt;/b&gt;입니다.&lt;br /&gt;특히 &lt;b&gt;체인(Chain), 에이전트(Agent)&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;size16&quot;&gt;즉, 단순한 텍스트 생성이 아니라, &lt;b&gt;검색&amp;middot;계산&amp;middot;API 호출 등의 외부 도구와 결합하여 보다 정교한 AI 애플리케이션을 구축하는 것&lt;/b&gt;이 핵심인 프레임워크라고 볼 수 있겠습니다.&lt;/p&gt;</description>
      <category>AI</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/240</guid>
      <comments>https://hmk1022.tistory.com/entry/LangChain%EC%9C%BC%EB%A1%9C-AI-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98#entry240comment</comments>
      <pubDate>Sat, 1 Feb 2025 11:36:06 +0900</pubDate>
    </item>
    <item>
      <title>레거시를 만들지 않기 위한 습관</title>
      <link>https://hmk1022.tistory.com/entry/%EB%A0%88%EA%B1%B0%EC%8B%9C%EB%A5%BC-%EB%A7%8C%EB%93%A4%EC%A7%80-%EC%95%8A%EA%B8%B0-%EC%9C%84%ED%95%9C-%EC%8A%B5%EA%B4%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;비즈니스는 속도가 생명이다.&quot; 초기 단계에서는 빠른 제품 출시와 시장 적응을 위해 효율성보다 결과를 우선시하기 쉽다. 이는 자연스럽게 기술 부채를 남기고, '레거시 코드'라 불리는 코드 뭉치나 비효율적인 아키텍처로 이어진다.&lt;/p&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;&quot;우리는 이 레거시 덕분에 지금까지 성장할 수 있었다.&quot; 라는 생각도 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;p data-ke-size=&quot;size16&quot;&gt;레거시는 단순히 &quot;오래된 코드&quot;를 의미하지 않는다. 본질적으로 &lt;b&gt;유지보수가 어렵고, 팀의 생산성을 저하시키는 시스템&lt;/b&gt;을 뜻한다. 이는 코드의 나이가 아니라 &lt;b&gt;구조적 문제, 복잡성, 문서화 부족, 또는 기술 부채&lt;/b&gt;로 인해 발생하는 결과이다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 다른 관점에서, 어떤 이들은 &lt;b&gt;코드는 배포된 순간부터 이미 레거시&lt;/b&gt;라고 말한다. 이는 코드가 시간이 지남에 따라 필연적으로 변화하는 요구사항, 새로운 기술 트렌드, 그리고 운영 환경에 적응해야 한다는 점에서 나온 의견이다. &lt;br /&gt;이런 변화 속에서 코드가 유지보수 가능성을 잃거나, 확장성을 고려하지 않은 상태로 남을 때, &quot;레거시&quot;라는 꼬리표가 붙게 된다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div data-message-model-slug=&quot;gpt-4o&quot; data-message-id=&quot;3ac1294a-d4d4-40d7-951a-e64e998502d6&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;아마 개발자라면 커리어 내내 맞닥뜨리게 될 딜레마가 있습니다. 바로, &lt;b&gt;&quot;확장성을 우선시할 것인가, 아니면 현재 필요성에 집중할 것인가&quot;&lt;/b&gt; 하는 선택입니다.&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;레거시를 만드는 개발습관엔 어떤 것들이 있을까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&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;b&gt;단기적인 해결책(핫픽스)에 의존하는 개발&lt;/b&gt;&lt;br /&gt;긴급한 문제 해결에만 집중하다 보면, 장기적으로 유지보수하기 어려운 코드가 쌓이게 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;불명확한 코드 구조와 네이밍&lt;/b&gt;&lt;br /&gt;가독성과 일관성이 떨어지는 코드와 애매한 네이밍은 팀원 간 의사소통을 어렵게 만듭니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;테스트와 자동화 부족&lt;/b&gt;&lt;br /&gt;테스트가 없으면 코드 변경 시 안정성을 보장하기 어렵고, 자동화가 없으면 반복적인 작업이 증가합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&quot;일단 동작하면 됐다&quot;는 태도&lt;/b&gt;&lt;br /&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;&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;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;레거시를 만들지 않기 위한 좋은 습관&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;1. &lt;b&gt;명확하고 일관된 코드 작성&lt;/b&gt;&lt;/h4&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;❌ temp1, doStuff()&lt;/li&gt;
&lt;li&gt;✅ userId, fetchUserData()&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;일관된 코드 스타일&lt;/b&gt;: 프로젝트 내에서 통일된 코딩 규칙(예: Prettier, ESLint)을 적용해 가독성을 유지합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명확한 타입과 변수 네이밍&lt;/p&gt;
&lt;pre id=&quot;code_1734261858069&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 나쁜 예
const t1 = (a: any, b: any): any =&amp;gt; a * b;

// 좋은 예
const calculateTotalPrice = (price: number, quantity: number): number =&amp;gt; price * quantity;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;명확한 인터페이스 정의&lt;/p&gt;
&lt;pre id=&quot;code_1734261892153&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 나쁜 예: 암시적으로 객체 사용
const createUser = (user: any) =&amp;gt; {
  console.log(user.name);
};

// 좋은 예: 명시적으로 인터페이스 사용
interface User {
  name: string;
  email: string;
}

const createUser = (user: User): void =&amp;gt; {
  console.log(user.name);
};&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;팀과 합의된 Eslint 규칙&lt;/p&gt;
&lt;pre id=&quot;code_1734262342945&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//@deprecated 주석된 변수나 함수에 경고
'deprecation/deprecation': 'warn',

//특정 키워드로 시작하는 주석에 경고
'no-warning-comments': [
  'warn',
  {
    terms: ['TODO', 'FIXME', 'TECH-DEBT', 'REFACTOR'],
    location: 'start',
  },
],
// 함수 중첩 깊이 제한
'max-depth': ['warn', 3],
// 함수 인자 개수 제한
'max-params': ['warn', 3],
// 중첩 콜백 제한
'max-nested-callbacks': ['warn', 3],
// 중첩된 삼항 연산자 방지
'no-nested-ternary': 'error',&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. &lt;b&gt;적절한 문서화와 주석 작성&lt;/b&gt;&lt;/h4&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;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1734261915880&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 나쁜 예: 주석이 부족하거나 의도를 설명하지 않음
function calculate(a: number, b: number): number {
  return a + b; // 더하기
}

// 좋은 예: 함수의 목적과 파라미터를 명확히 문서화
/**
 * 두 숫자의 합계를 계산하는 함수
 * @param a - 첫 번째 숫자
 * @param b - 두 번째 숫자
 * @returns 합계
 */
function calculateSum(a: number, b: number): number {
  return a + b;
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. &lt;b&gt;테스트 주도 개발(TDD) 또는 테스트 우선 문화&lt;/b&gt;&lt;/h4&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;: 단위 테스트, 통합 테스트, E2E 테스트를 통해 코드 변경 시 안정성을 보장합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;테스트 커버리지 확인&lt;/b&gt;: 100% 커버리지가 목표는 아니지만, 주요 로직은 반드시 테스트를 작성합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드품질 보장, 안정적인 코드 변경지원, 문서화 역할, 코드 설계 개선 등등의 이점도 챙길 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;코드 수정 시 테스트 결과를 통해 빠르게 문제를 발견하고 해결할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1734261928301&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 테스트 작성
describe(&quot;calculateTotalPrice&quot;, () =&amp;gt; {
  it(&quot;should return the correct total price&quot;, () =&amp;gt; {
    expect(calculateTotalPrice(100, 2)).toBe(200);
  });
});

// 코드 구현
const calculateTotalPrice = (price: number, quantity: number): number =&amp;gt; price * quantity;&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. &lt;b&gt;점진적 리팩토링 습관화&lt;/b&gt;&lt;/h4&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;b&gt;작은 빚부터 갚는 습관&lt;/b&gt;을 기릅니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예: 함수 분리, 반복되는 코드 제거, 오래된 의존성 업데이트 등.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1734261941408&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 리팩토링 전: 중복된 코드
function sendEmailToAdmin(user: { email: string }): string {
  const email = user.email;
  if (!email) return &quot;Email not found&quot;;
  // 이메일 전송 로직
  return &quot;Admin email sent&quot;;
}

function sendEmailToCustomer(user: { email: string }): string {
  const email = user.email;
  if (!email) return &quot;Email not found&quot;;
  // 이메일 전송 로직
  return &quot;Customer email sent&quot;;
}

// 리팩토링 후: 공통 로직 분리
function sendEmail(user: { email: string }, role: &quot;Admin&quot; | &quot;Customer&quot;): string {
  const email = user.email;
  if (!email) return &quot;Email not found&quot;;
  // 이메일 전송 로직
  return `${role} email sent`;
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5. &lt;b&gt;적절한 확장성과 단순성의 균형 유지&lt;/b&gt;&lt;/h4&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예: YAGNI(You Aren't Gonna Need It) 원칙을 따르면서도, 인터페이스 설계나 모듈화를 통해 유연성을 확보합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;복잡한 아키텍처보다 &lt;b&gt;KISS(Keep It Simple, Stupid)&lt;/b&gt; 원칙을 따라 단순한 설계를 우선합니다.&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;https://velog.io/@wngud4950/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C-3%EB%8C%80-%EC%9B%90%EC%B9%99-KISS-YAGNI-DRY&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://velog.io/@wngud4950/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C-3%EB%8C%80-%EC%9B%90%EC%B9%99-KISS-YAGNI-DRY&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure id=&quot;og_1734262000942&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;소프트웨어 개발 3대 원칙 (KISS, YAGNI, DRY)&quot; data-og-description=&quot;소프트웨어를 알흠답고 잘 짜기 위한KISS(키쓰!) YAGNI(야근!!) DRY(드롸이!!)를 알아보자아직까지 별 거 없는 실력이지만 프로젝트를 한 두어개 해보다보니까 구현 이후 깔끔한 코드를 어떻게 짜는 &quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@wngud4950/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C-3%EB%8C%80-%EC%9B%90%EC%B9%99-KISS-YAGNI-DRY&quot; data-og-url=&quot;https://velog.io/@wngud4950/소프트웨어-개발-3대-원칙-KISS-YAGNI-DRY&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/5rzRM/hyXOfYiWa2/IjUEQMLM5mwXNrhdtTZpG0/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500&quot;&gt;&lt;a href=&quot;https://velog.io/@wngud4950/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C-3%EB%8C%80-%EC%9B%90%EC%B9%99-KISS-YAGNI-DRY&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@wngud4950/%EC%86%8C%ED%94%84%ED%8A%B8%EC%9B%A8%EC%96%B4-%EA%B0%9C%EB%B0%9C-3%EB%8C%80-%EC%9B%90%EC%B9%99-KISS-YAGNI-DRY&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/5rzRM/hyXOfYiWa2/IjUEQMLM5mwXNrhdtTZpG0/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500');&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;소프트웨어 개발 3대 원칙 (KISS, YAGNI, DRY)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;소프트웨어를 알흠답고 잘 짜기 위한KISS(키쓰!) YAGNI(야근!!) DRY(드롸이!!)를 알아보자아직까지 별 거 없는 실력이지만 프로젝트를 한 두어개 해보다보니까 구현 이후 깔끔한 코드를 어떻게 짜는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.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;
&lt;pre id=&quot;code_1734261977263&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 나쁜 예: 지나치게 복잡한 설계
function calculatePrice(price: number, tax: number, discount?: number, additionalFees?: number): number {
  return price + tax - (discount || 0) + (additionalFees || 0);
}

// 좋은 예: 현재 요구사항에 맞는 단순한 설계
function calculatePrice(price: number, tax: number): number {
  return price + tax;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;6. &lt;b&gt;도메인 지식 공유&lt;/b&gt;&lt;/h4&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;팀 내 기술 공유 세션:&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;지난주에 작업한 '상품 추천 알고리즘'은 사용자 행동 데이터를 기반으로 추천을 제공하는 로직입니다. 이를 통해 개인화 추천의 정확도를 15% 개선할 수 있었습니다.&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;코드 베이스 이해를 돕는 문서화&lt;/p&gt;
&lt;pre id=&quot;code_1734262052295&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/**
 * 사용자 추천 알고리즘
 * @param userId - 추천할 사용자 ID
 * @returns 추천 상품 배열
 */
function recommendProducts(userId: string): string[] {
  // 추천 알고리즘 로직
  return [&quot;Product1&quot;, &quot;Product2&quot;];
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;7.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;리팩토링 효율성 파악하기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;git 명령어를 통해 수정이 빈번한 파일 정렬해서 출력하기&lt;/p&gt;
&lt;pre id=&quot;code_1734263041733&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;git log --name-only --pretty=format: |
sed -e 's|^pages/|^apps/mercedes/pages/|g' -e 's|^src/|^apps/mercedes/src/|g' |
grep -E '^(apps/mercedes/src|apps/mercedes/pages)' |
awk 'NR==FNR{a[$0];next} $0 in a' &amp;lt;(git ls-files) - |
sort | uniq -c | sort -nr


# --since=&quot;3 months ago&quot;
git log --name-only --since=&quot;30 days ago&quot; --pretty=format: |
sed -e 's|^pages/|^apps/mercedes/pages/|g' -e 's|^src/|^apps/mercedes/src/|g' |
grep -E '^(apps/mercedes/src|apps/mercedes/pages)' |
awk 'NR==FNR{a[$0];next} $0 in a' &amp;lt;(git ls-files) - |
sort | uniq -c | sort -nr&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;pre id=&quot;code_1734263079118&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;687 apps/mercedes/src/service/ABTestingPolicyService.ts
322 apps/mercedes/pages/index.tsx
306 apps/mercedes/src/component/HomePage/index.tsx
301 apps/mercedes/pages/plans/[id].tsx
262 apps/mercedes/pages/plans/index.tsx
233 apps/mercedes/src/log/types/logNavigationTypes.ts
210 apps/mercedes/pages/_app.tsx
189 apps/mercedes/src/component/PlanDetailPage/SignUpInfoSection/index.tsx
165 apps/mercedes/src/component/MyOrderDetailPage/index.tsx
149 apps/mercedes/src/entity/plan.ts
113 apps/mercedes/src/component/TipsDetailPage/index.tsx
113 apps/mercedes/src/common/constants.ts
104 apps/mercedes/src/common/web-util.ts
100 apps/mercedes/src/component/StockAlarmPage/index.tsx
94 apps/mercedes/src/shared/components/surfaces/Card/PlanCard/PlanCard.tsx
86 apps/mercedes/src/component/PhoneContentsPage/index.tsx
83 apps/mercedes/src/component/ShorterPlanDetail/index.tsx
80 apps/mercedes/src/component/MyPagePageV2/BottomListSection.tsx
80 apps/mercedes/src/api/planOrder/planOrderLg.ts
78 apps/mercedes/pages/event.tsx
75 apps/mercedes/src/entity/api.ts
75 apps/mercedes/pages/tips/detail/[id].tsx
70 apps/mercedes/src/entity/mvnos.ts
70 apps/mercedes/src/component/InternetsPage/index.tsx
70 apps/mercedes/pages/calculator/plans-by-data/start.tsx
66 apps/mercedes/src/modules/MvnoCardList/MvnoCardList.module.scss
66 apps/mercedes/src/component/MyOrdersPage/OrderProgressFaqSection.tsx
66 apps/mercedes/src/common/http-util.ts
66 apps/mercedes/pages/tips.tsx
65 apps/mercedes/src/component/ReferralCodePage/indexV2.tsx
64 apps/mercedes/src/component/PlanDetailPage/PlanInfoSection/PlanInfoSection.module.scss
64 apps/mercedes/src/api/plan.ts
63 apps/mercedes/src/modules/Header/Header.tsx
63 apps/mercedes/src/component/PlanBridgePage/index.tsx
61 apps/mercedes/src/log/types/logObjectTypes.ts
59 apps/mercedes/src/component/InternetRequestPage/index.tsx
59 apps/mercedes/pages/referral/register.tsx
58 apps/mercedes/pages/login/kakao/index.tsx
57 apps/mercedes/src/modules/plans/layouts/PlanSearchFilters/PlanSearchFilters.tsx
57 apps/mercedes/src/entity/order/order.ts
57 apps/mercedes/pages/mypage/index.tsx
56 apps/mercedes/src/modules/BannerSlider/index.tsx
54 apps/mercedes/pages/community/questions/[...params].tsx
51 apps/mercedes/src/common/mvno-util.ts
51 apps/mercedes/pages/internets/index.tsx
50 apps/mercedes/src/modules/EventList/index.tsx
50 apps/mercedes/src/component/MyOrdersPage/OrderProgressSection.tsx
50 apps/mercedes/src/component/AffiliatePage/resultV3.tsx
50 apps/mercedes/pages/_document.tsx
49 apps/mercedes/src/component/PhoneContentsPage/phone-contents.ts
49 apps/mercedes/src/component/MvnoDetailPage/index.tsx
49 apps/mercedes/src/component/LoginPage/index.tsx
49 apps/mercedes/pages/_error.tsx
48 apps/mercedes/src/shared/utils/sendBehaviorLogScheduler.ts
48 apps/mercedes/src/component/TipsDetailPage/generate.tsx
48 apps/mercedes/src/component/PlanOrderPageV2/PlanOrderSerializer.ts
48 apps/mercedes/src/component/MyOrderDetailPage/ActivationRequestPage.tsx&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/239</guid>
      <comments>https://hmk1022.tistory.com/entry/%EB%A0%88%EA%B1%B0%EC%8B%9C%EB%A5%BC-%EB%A7%8C%EB%93%A4%EC%A7%80-%EC%95%8A%EA%B8%B0-%EC%9C%84%ED%95%9C-%EC%8A%B5%EA%B4%80#entry239comment</comments>
      <pubDate>Sun, 15 Dec 2024 20:45:07 +0900</pubDate>
    </item>
    <item>
      <title>C++ 과 javascript</title>
      <link>https://hmk1022.tistory.com/entry/C-%EA%B3%BC-javascript</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;프론트엔드 개발자가 C++를 알면 여러 측면에서 이점을 가질 수 있습니다. C++는 성능과 시스템 수준의 프로그래밍에 강점을 가지고 있어, 프론트엔드 개발에 직접적으로 사용되지는 않지만 다음과 같은 간접적인 이점이 있습니다:&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++를 자바스크립트와 비교하여 기초부터 배우고 싶다면, 두 언어의 주요 차이점과 개념을 중심으로 설명해 보겠습니다. C++는 컴파일러 언어이고, 자바스크립트는 인터프리터 언어라는 근본적인 차이가 있으며, 이에 따라 메모리 관리, 데이터 타입, 흐름 제어 등 다양한 측면에서 차이가 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bK6ltP/btsKcO8Y0vz/I35F8mvxjJMSS5hqhlsT7K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bK6ltP/btsKcO8Y0vz/I35F8mvxjJMSS5hqhlsT7K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bK6ltP/btsKcO8Y0vz/I35F8mvxjJMSS5hqhlsT7K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbK6ltP%2FbtsKcO8Y0vz%2FI35F8mvxjJMSS5hqhlsT7K%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;1000&quot; height=&quot;500&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;500&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;성능 최적화에 대한 깊은 이해&lt;/b&gt;: C++는 메모리 관리와 성능 최적화에 매우 민감한 언어입니다. 이를 통해 자바스크립트 엔진의 동작 원리나 브라우저 내부의 성능 최적화 과정에 대한 더 깊은 이해를 할 수 있습니다. V8 같은 자바스크립트 엔진은 C++로 구현되어 있기 때문에, C++를 알면 이러한 엔진의 내부 작동을 더 잘 이해하고 성능 문제를 효율적으로 해결할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;WebAssembly와 연계&lt;/b&gt;: WebAssembly는 브라우저에서 C++ 같은 고성능 언어를 실행할 수 있는 기술입니다. C++를 알면 WebAssembly로 고성능 애플리케이션을 개발하거나 성능이 중요한 부분을 최적화하는 데 유리합니다. 프론트엔드 개발에서 성능이 중요한 애플리케이션(예: 게임, 영상 처리 등)을 만들 때 C++와 WebAssembly는 강력한 조합이 될 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;데이터 구조와 알고리즘의 깊은 이해&lt;/b&gt;: C++를 공부하면서 메모리 관리, 효율적인 데이터 구조, 고급 알고리즘에 대한 깊은 이해를 얻게 됩니다. 이는 프론트엔드 개발에서도 복잡한 애플리케이션을 설계할 때 중요한 자산이 될 수 있습니다. 특히 대규모 상태 관리나 성능 최적화에서 도움이 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다양한 도구 개발&lt;/b&gt;: C++는 고성능 도구나 라이브러리 개발에 자주 사용됩니다. 프론트엔드 개발에 필요한 맞춤형 빌드 툴이나 성능을 극대화한 라이브러리를 직접 개발할 수 있습니다. 이런 도구는 개발 효율성을 크게 높일 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;브라우저 확장 및 통합&lt;/b&gt;: 브라우저의 확장 기능이나 플러그인을 만들 때, C++ 같은 언어로 작성된 네이티브 모듈을 사용하여 복잡한 연산을 처리하거나 시스템 수준의 기능과 상호작용할 수 있습니다. 프론트엔드와 백엔드, 그리고 시스템 프로그래밍을 통합하는 데 유용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;저수준 프로그래밍 경험&lt;/b&gt;: C++는 자바스크립트보다 훨씬 저수준의 프로그래밍 언어입니다. 이 경험은 자바스크립트 같은 고수준 언어에서 발생하는 문제들을 더 깊이 이해하고, 최적화 포인트를 찾는 데 도움이 될 수 있습니다.&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;자바스크립트를 주로 사용했던 프론트엔드 개발자로써 위에 대한 공부, 의도적수련을 하기위해 javascript와 c++을 비교하는 글을 작성해보고자 합니다.&lt;/p&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;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;C++ vs Javascript&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. &lt;b&gt;변수 선언 및 데이터 타입&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트는 동적 타입 언어이고, C++는 정적 타입 언어입니다. 자바스크립트에서는 변수의 타입을 명시하지 않고 선언할 수 있지만, C++에서는 변수의 타입을 명시해야 합니다.&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;/h3&gt;
&lt;pre id=&quot;code_1729427388416&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let x = 10;    // 숫자
let y = &quot;Hello&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;p data-ke-size=&quot;size16&quot;&gt;C++&lt;/p&gt;
&lt;pre id=&quot;code_1729427422572&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int x = 10;    // 정수
std::string y = &quot;Hello&quot;;  // 문자열 (C++에서 문자열은 `std::string` 객체로 다룸)&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;b&gt;차이점&lt;/b&gt;: C++에서는 변수를 선언할 때 &lt;b&gt;명시적인 타입&lt;/b&gt;을 지정해야 합니다. 또한, 자바스크립트의 let, const처럼 변수 범위를 지정하는 키워드가 있는 반면, C++에서는 int, double, char 등의 타입을 지정합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. &lt;b&gt;메모리 관리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트는 가비지 컬렉션(Garbage Collection)을 통해 메모리를 자동으로 관리합니다. 하지만 C++는 개발자가 직접 메모리를 할당하고 해제해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자바스크립트&lt;/h3&gt;
&lt;pre id=&quot;code_1729427446414&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let obj = { name: &quot;John&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;C++&lt;/p&gt;
&lt;pre id=&quot;code_1729427466416&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int* ptr = new int;  // 메모리 동적 할당
delete ptr;          // 메모리 해제&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;b&gt;차이점&lt;/b&gt;: C++에서는 new와 delete 키워드를 사용하여 직접 메모리를 할당하고 해제해야 합니다. 이 점에서 C++는 메모리 관리에 더 신경 써야 하는 반면, 자바스크립트는 이를 자동으로 처리합니다.&lt;/p&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;h2 data-ke-size=&quot;size26&quot;&gt;3. &lt;b&gt;함수 선언&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트와 C++ 모두 함수 선언 방식은 비슷하지만, C++는 함수의 반환 타입을 명시해야 합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자바스크립트&lt;/h3&gt;
&lt;pre id=&quot;code_1729427528830&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function add(a, b) {
  return a + b;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++&lt;/p&gt;
&lt;pre id=&quot;code_1729427541549&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int add(int a, int b) {
    return a + b;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. &lt;b&gt;조건문 및 반복문&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조건문(if, else)과 반복문(for, while)의 구조는 두 언어에서 매우 비슷합니다.&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;/h3&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1729427559630&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (x &amp;gt; 10) {
  console.log(&quot;x는 10보다 큽니다.&quot;);
}

for (let i = 0; i &amp;lt; 5; i++) {
  console.log(i);
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;C++&lt;/p&gt;
&lt;pre id=&quot;code_1729427571960&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;if (x &amp;gt; 10) {
    std::cout &amp;lt;&amp;lt; &quot;x는 10보다 큽니다.&quot; &amp;lt;&amp;lt; std::endl;
}

for (int i = 0; i &amp;lt; 5; i++) {
    std::cout &amp;lt;&amp;lt; i &amp;lt;&amp;lt; std::endl;
}&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;b&gt;차이점&lt;/b&gt;: 기본적인 제어 흐름은 비슷하지만, C++에서는 입출력에 std::cout과 같은 표준 라이브러리 함수를 사용하며, 자바스크립트는 console.log()를 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. &lt;b&gt;클래스와 객체 지향 프로그래밍&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트와 C++는 둘 다 객체 지향 프로그래밍(OOP)을 지원하지만, C++는 클래스 기반 OOP를 처음부터 설계에 반영한 반면, 자바스크립트는 프로토타입 기반 OOP를 사용하다가 클래스 문법이 추가되었습니다.&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;/h3&gt;
&lt;pre id=&quot;code_1729427643606&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person {
  constructor(name) {
    this.name = name;
  }
  
  greet() {
    console.log(`Hello, ${this.name}`);
  }
}

let person = new Person(&quot;Alice&quot;);
person.greet();  // Hello, Alice&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;C++&lt;/p&gt;
&lt;pre id=&quot;code_1729427653297&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person {
public:
    std::string name;
    
    Person(std::string n) : name(n) {}
    
    void greet() {
        std::cout &amp;lt;&amp;lt; &quot;Hello, &quot; &amp;lt;&amp;lt; name &amp;lt;&amp;lt; std::endl;
    }
};

Person person(&quot;Alice&quot;);
person.greet();  // Hello, Alice&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;b&gt;차이점&lt;/b&gt;: C++는 클래스에서 &lt;b&gt;접근 지정자&lt;/b&gt;(예: public, private)를 사용하여 멤버 변수와 함수를 관리합니다. 자바스크립트는 접근 지정자를 명시적으로 사용하지 않으며, 모든 멤버가 기본적으로 public입니다. 또, C++에서는 생성자 초기화 목록을 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. &lt;b&gt;포인터와 참조&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++는 &lt;b&gt;포인터&lt;/b&gt;와 &lt;b&gt;참조&lt;/b&gt;라는 중요한 개념을 가지고 있습니다. 자바스크립트는 이러한 저수준 개념이 없으며, 변수가 값 자체를 저장하거나 객체에 대한 참조를 자동으로 관리합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;자바스크립트&lt;/h3&gt;
&lt;pre id=&quot;code_1729427803610&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let obj = { name: &quot;Alice&quot; };
let ref = obj;  // obj에 대한 참조
ref.name = &quot;Bob&quot;;
console.log(obj.name);  // Bob (참조로 인해 원본 객체 변경)&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;C++&lt;/p&gt;
&lt;pre id=&quot;code_1729427820660&quot; class=&quot;cpp&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;cpp&quot;&gt;&lt;code&gt;int a = 5;
int* p = &amp;amp;a;  // a의 주소를 저장하는 포인터
*p = 10;      // 포인터를 통해 a의 값을 변경
std::cout &amp;lt;&amp;lt; a &amp;lt;&amp;lt; std::endl;  // 10&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;b&gt;차이점&lt;/b&gt;: C++는 &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;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;7. &lt;b&gt;컴파일과 실행&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++는 컴파일러 기반 언어로, 코드를 작성한 후에 컴파일 과정이 필요합니다. 반면 자바스크립트는 브라우저나 Node.js에서 바로 실행할 수 있는 인터프리터 언어입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;C++ 컴파일&lt;/h3&gt;
&lt;pre id=&quot;code_1729428149320&quot; class=&quot;cpp&quot; data-ke-language=&quot;cpp&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;g++ main.cpp -o main
./main&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;자바스크립트 실행&lt;/p&gt;
&lt;pre id=&quot;code_1729428164920&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;node script.js&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;b&gt;차이점&lt;/b&gt;: C++는 컴파일 단계를 거쳐야 하기 때문에, 코드가 실행되기 전에 컴파일러가 오류를 잡아냅니다. 반면 자바스크립트는 실행할 때까지 오류가 감지되지 않는 경우가 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;C++ 와 컴퓨터 작동 원리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++를 공부하면 컴퓨터 작동 원리, 메모리 관리, 성능 최적화에 대해 깊이 이해할 수 있는 이유는 C++가 저수준 프로그래밍 언어로서 컴퓨터 하드웨어와 가까운 방식으로 작동하기 때문입니다. 이를 통해 컴퓨터 내부에서 일어나는 일을 더 구체적으로 제어하고 이해할 수 있습니다. 구체적인 예시와 설명을 통해 그 이유를 살펴보겠습니다.&lt;/p&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;h3 data-ke-size=&quot;size23&quot;&gt;1. &lt;b&gt;메모리 관리와 포인터&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++는 개발자가 직접 메모리를 할당하고 해제할 수 있도록 하며, 이를 통해 메모리 사용의 효율성을 극대화할 수 있습니다. 이는 &lt;b&gt;메모리 구조&lt;/b&gt;와 &lt;b&gt;컴퓨터의 메모리 관리 방식&lt;/b&gt;을 더 깊이 이해하게 만드는 중요한 이유입니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예시: 동적 메모리 할당&lt;/h4&gt;
&lt;pre id=&quot;code_1729428455483&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int* ptr = new int(10); // 힙 영역에 메모리 할당
std::cout &amp;lt;&amp;lt; *ptr &amp;lt;&amp;lt; std::endl; // 포인터를 통해 메모리 접근

delete ptr; // 메모리 해제&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;C++에서 new를 사용해 메모리를 할당하면 **힙(Heap)**이라는 메모리 영역에 공간이 생깁니다. 개발자가 필요할 때 메모리를 할당하고, 더 이상 필요하지 않으면 delete로 해제하는 방식으로 메모리를 관리합니다. 이 과정을 통해 메모리 관리의 복잡성과 중요성을 이해하게 되며, 자동 메모리 관리(Garbage Collection)가 없는 환경에서는 메모리 누수(memory leak)와 같은 문제를 방지하는 방법을 배울 수 있습니다.&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;: 자바스크립트나 다른 고수준 언어는 메모리 관리를 자동으로 처리하지만, C++에서는 개발자가 직접 제어합니다. 이를 통해 메모리가 어떻게 할당되고 해제되는지, 메모리 누수 문제가 왜 발생하는지, 최적의 메모리 관리를 위해 어떤 전략을 사용해야 하는지 알게 됩니다.&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;2. &lt;b&gt;포인터와 메모리 주소&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++에서 포인터는 &lt;b&gt;메모리 주소&lt;/b&gt;를 다룹니다. 포인터는 변수나 객체가 저장된 메모리 위치를 참조하는데, 이를 통해 메모리 상의 데이터 구조가 어떻게 배치되는지를 이해할 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예시: 포인터와 배열&lt;/h4&gt;
&lt;pre id=&quot;code_1729428478969&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int arr[3] = {1, 2, 3};
int* p = arr; // 배열 첫 번째 요소의 주소를 가리킴

std::cout &amp;lt;&amp;lt; *(p+1) &amp;lt;&amp;lt; std::endl; // 배열의 두 번째 요소 접근&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;이 예에서 p는 배열의 첫 번째 요소를 가리키고, 포인터 연산을 통해 배열 내의 다른 요소에 접근할 수 있습니다. 포인터를 이해하면 메모리 내에서 데이터가 어떻게 저장되고 이동되는지, 특히 다차원 배열이나 동적 데이터 구조에서 어떻게 효율적으로 접근할 수 있는지 배우게 됩니다.&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;: 포인터는 데이터를 메모리 상에서 직접 다루는 방식을 보여주며, 이를 통해 컴퓨터 메모리의 계층 구조(스택, 힙 등)를 이해하고, 메모리 접근 성능에 대해 고민할 수 있게 합니다.&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;3. &lt;b&gt;캐시 및 성능 최적화&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++는 CPU의 캐시 메모리와 메인 메모리 간의 상호작용을 고려한 코드를 작성할 때 특히 유용합니다. 효율적인 코드 작성은 **캐시 미스(cache miss)**를 줄이고, 데이터 접근을 최적화하는 것을 목표로 할 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예시: 배열 순회 성능 차이&lt;/h4&gt;
&lt;pre id=&quot;code_1729428634260&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const int size = 10000;
int matrix[size][size];

// 행 순서로 순회
for (int i = 0; i &amp;lt; size; i++) {
    for (int j = 0; j &amp;lt; size; j++) {
        matrix[i][j] = i + j;
    }
}

// 열 순서로 순회
for (int j = 0; j &amp;lt; size; j++) {
    for (int i = 0; i &amp;lt; size; i++) {
        matrix[i][j] = i + j;
    }
}&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;b&gt;행 순서로 순회&lt;/b&gt;하는 것이 &lt;b&gt;열 순서로 순회&lt;/b&gt;하는 것보다 성능이 더 좋습니다. 그 이유는 캐시 메모리의 작동 방식 때문입니다. CPU 캐시는 메모리를 작은 블록 단위로 가져오는데, 배열을 행 순서로 순회하면 캐시가 효율적으로 동작(캐시 히트가 자주 발생)하여 성능이 향상됩니다. 열 순서로 순회하면 캐시 미스가 자주 발생하여 성능이 떨어집니다.&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;: 배열이나 데이터 구조의 순회 방식만으로도 성능이 크게 달라질 수 있다는 것을 C++에서 배우면, 컴퓨터 하드웨어가 데이터를 어떻게 처리하는지 더 깊이 이해하게 되고, 이를 통해 성능 최적화 전략을 세울 수 있습니다.&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;4. &lt;b&gt;멀티스레딩과 동시성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++는 멀티스레딩과 동시성을 지원하는 강력한 기능을 가지고 있습니다. 멀티스레딩은 CPU 자원을 효율적으로 활용하기 위한 방법 중 하나로, 이를 사용하면 &lt;b&gt;병렬 처리&lt;/b&gt;를 통해 프로그램의 성능을 극대화할 수 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;예시: 멀티스레딩&lt;/h4&gt;
&lt;pre id=&quot;code_1729428711061&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
#include &amp;lt;thread&amp;gt;

void task1() {
    std::cout &amp;lt;&amp;lt; &quot;Task 1\n&quot;;
}

void task2() {
    std::cout &amp;lt;&amp;lt; &quot;Task 2\n&quot;;
}

int main() {
    std::thread t1(task1);
    std::thread t2(task2);

    t1.join();
    t2.join();
    return 0;
}&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;이 예제에서는 두 개의 스레드를 생성하여 각각 task1과 task2를 동시에 실행합니다. 멀티스레딩을 통해 여러 작업을 병렬로 처리할 수 있으며, 이를 통해 CPU 사용량을 극대화할 수 있습니다.&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;: 멀티스레딩을 사용하면 컴퓨터의 &lt;b&gt;프로세서&lt;/b&gt;가 병렬로 작업을 처리하는 방식을 이해하게 되고, &lt;b&gt;경쟁 조건&lt;/b&gt;이나 &lt;b&gt;데드락&lt;/b&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;div&gt;
&lt;div data-message-model-slug=&quot;gpt-4o&quot; data-message-id=&quot;ad9c4aed-7641-4008-a317-880f57f0db64&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;결론: C++를 통해 얻는 시스템 및 성능에 대한 이해&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C++는 하드웨어와 가까운 수준에서 프로그래밍을 할 수 있도록 해줍니다. 메모리 관리, 포인터, 멀티스레딩 등 시스템 자원을 효율적으로 관리하는 방법을 배우면서 &lt;b&gt;컴퓨터의 작동 원리&lt;/b&gt;와 &lt;b&gt;성능 최적화&lt;/b&gt;에 대한 깊은 이해를 얻을 수 있습니다. 자바스크립트와 같은 고수준 언어를 사용할 때는 자동으로 처리되는 부분들이 C++에서는 명시적으로 드러나기 때문에, 시스템의 작동 방식과 최적화의 중요성을 체감하게 됩니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&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>의도적수련</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/237</guid>
      <comments>https://hmk1022.tistory.com/entry/C-%EA%B3%BC-javascript#entry237comment</comments>
      <pubDate>Sun, 20 Oct 2024 22:00:23 +0900</pubDate>
    </item>
    <item>
      <title>yarn plugin으로 우아하게 로깅하기</title>
      <link>https://hmk1022.tistory.com/entry/yarn-plugin%EC%9C%BC%EB%A1%9C-%EC%9A%B0%EC%95%84%ED%95%98%EA%B2%8C-%EB%A1%9C%EA%B9%85%ED%95%98%EA%B8%B0</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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2006&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIJpYZ/btsKbARhQol/tu8h1DDXKWWxupa7gtr541/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIJpYZ/btsKbARhQol/tu8h1DDXKWWxupa7gtr541/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIJpYZ/btsKbARhQol/tu8h1DDXKWWxupa7gtr541/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIJpYZ%2FbtsKbARhQol%2Ftu8h1DDXKWWxupa7gtr541%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;2006&quot; height=&quot;1024&quot; data-origin-width=&quot;2006&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2208&quot; data-origin-height=&quot;1222&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSs9Pd/btsKcdt4RXT/NsNihU6fyrCmGUoaajzq3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSs9Pd/btsKcdt4RXT/NsNihU6fyrCmGUoaajzq3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSs9Pd/btsKcdt4RXT/NsNihU6fyrCmGUoaajzq3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSs9Pd%2FbtsKcdt4RXT%2FNsNihU6fyrCmGUoaajzq3k%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;2208&quot; height=&quot;1222&quot; data-origin-width=&quot;2208&quot; data-origin-height=&quot;1222&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2108&quot; data-origin-height=&quot;1048&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x5u98/btsKbffugAS/5QAyiBsNBFLm1GM7Mpguf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x5u98/btsKbffugAS/5QAyiBsNBFLm1GM7Mpguf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x5u98/btsKbffugAS/5QAyiBsNBFLm1GM7Mpguf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx5u98%2FbtsKbffugAS%2F5QAyiBsNBFLm1GM7Mpguf0%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;2108&quot; height=&quot;1048&quot; data-origin-width=&quot;2108&quot; data-origin-height=&quot;1048&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;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;2178&quot; data-origin-height=&quot;1050&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wTsWe/btsKbE64yd6/qrqwgS3lyj4QCYKYMggiHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wTsWe/btsKbE64yd6/qrqwgS3lyj4QCYKYMggiHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wTsWe/btsKbE64yd6/qrqwgS3lyj4QCYKYMggiHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwTsWe%2FbtsKbE64yd6%2FqrqwgS3lyj4QCYKYMggiHk%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;2178&quot; height=&quot;1050&quot; data-origin-width=&quot;2178&quot; data-origin-height=&quot;1050&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;p data-ke-size=&quot;size16&quot;&gt;토스는 자체 디자인 시스템인 TDS를 이용해 로깅을 자동화했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2208&quot; data-origin-height=&quot;1006&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Emwbn/btsKcNvfgth/wTLdqfkdL30lJLOX2r6Dy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Emwbn/btsKcNvfgth/wTLdqfkdL30lJLOX2r6Dy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Emwbn/btsKcNvfgth/wTLdqfkdL30lJLOX2r6Dy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEmwbn%2FbtsKcNvfgth%2FwTLdqfkdL30lJLOX2r6Dy0%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;2208&quot; height=&quot;1006&quot; data-origin-width=&quot;2208&quot; data-origin-height=&quot;1006&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;h4 data-ke-size=&quot;size20&quot;&gt;첫번째 시도 - 디자인시스템에 로그 기능을 추가하자&lt;/h4&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;2186&quot; data-origin-height=&quot;1184&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNazul/btsKbU2SjZn/ZsFNJ3pj5azBHNCkyU0r8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNazul/btsKbU2SjZn/ZsFNJ3pj5azBHNCkyU0r8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNazul/btsKbU2SjZn/ZsFNJ3pj5azBHNCkyU0r8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNazul%2FbtsKbU2SjZn%2FZsFNJ3pj5azBHNCkyU0r8k%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;2186&quot; height=&quot;1184&quot; data-origin-width=&quot;2186&quot; data-origin-height=&quot;1184&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2192&quot; data-origin-height=&quot;1016&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bl4fu6/btsKcjA6doE/pF1DKsKgOnXev8ESW1yCPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bl4fu6/btsKcjA6doE/pF1DKsKgOnXev8ESW1yCPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bl4fu6/btsKcjA6doE/pF1DKsKgOnXev8ESW1yCPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbl4fu6%2FbtsKcjA6doE%2FpF1DKsKgOnXev8ESW1yCPk%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;2192&quot; height=&quot;1016&quot; data-origin-width=&quot;2192&quot; data-origin-height=&quot;1016&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;p data-ke-size=&quot;size16&quot;&gt;TDS가 로깅관련 코드를 포함해 로깅관련 수정사항을 반영하면 모든 컴포넌트의 디자인 사양도 변경해야하는 문제도 발생했다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2040&quot; data-origin-height=&quot;1086&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o7eX4/btsKdwTRISI/CnkZTJgkaswrkEYm6OcVg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o7eX4/btsKdwTRISI/CnkZTJgkaswrkEYm6OcVg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o7eX4/btsKdwTRISI/CnkZTJgkaswrkEYm6OcVg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo7eX4%2FbtsKdwTRISI%2FCnkZTJgkaswrkEYm6OcVg0%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;2040&quot; height=&quot;1086&quot; data-origin-width=&quot;2040&quot; data-origin-height=&quot;1086&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;두번째 시도 -   HOC 형태로 로그 감싸기&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2128&quot; data-origin-height=&quot;1046&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dtl0q9/btsKcOHH5Kn/t7THhhREuYMqEWCObIiO00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dtl0q9/btsKcOHH5Kn/t7THhhREuYMqEWCObIiO00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dtl0q9/btsKcOHH5Kn/t7THhhREuYMqEWCObIiO00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdtl0q9%2FbtsKcOHH5Kn%2Ft7THhhREuYMqEWCObIiO00%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;2128&quot; height=&quot;1046&quot; data-origin-width=&quot;2128&quot; data-origin-height=&quot;1046&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2162&quot; data-origin-height=&quot;1064&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BnWsi/btsKbEF1ymG/CyEQd8lQUQqDoKff8RHU0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BnWsi/btsKbEF1ymG/CyEQd8lQUQqDoKff8RHU0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BnWsi/btsKbEF1ymG/CyEQd8lQUQqDoKff8RHU0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBnWsi%2FbtsKbEF1ymG%2FCyEQd8lQUQqDoKff8RHU0K%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;2162&quot; height=&quot;1064&quot; data-origin-width=&quot;2162&quot; data-origin-height=&quot;1064&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;TDS 컴포넌트를 감싸 제공하는 형태로 제공,&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;그러나, 로깅 레이어를 사용하기 위해서 기존의 tds대신 hoc가 적용된 tds 컴포넌트를 사용해야했음&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;2136&quot; data-origin-height=&quot;1114&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cikQHB/btsKdmKy0pd/5aarQcs9NeWDTFKB0Pdzqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cikQHB/btsKdmKy0pd/5aarQcs9NeWDTFKB0Pdzqk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cikQHB/btsKdmKy0pd/5aarQcs9NeWDTFKB0Pdzqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcikQHB%2FbtsKdmKy0pd%2F5aarQcs9NeWDTFKB0Pdzqk%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;2136&quot; height=&quot;1114&quot; data-origin-width=&quot;2136&quot; data-origin-height=&quot;1114&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;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;1962&quot; data-origin-height=&quot;826&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nOBDr/btsKccPBPiQ/AY3zKELYXRBOPwtmdzjFb1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nOBDr/btsKccPBPiQ/AY3zKELYXRBOPwtmdzjFb1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nOBDr/btsKccPBPiQ/AY3zKELYXRBOPwtmdzjFb1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnOBDr%2FbtsKccPBPiQ%2FAY3zKELYXRBOPwtmdzjFb1%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;1962&quot; height=&quot;826&quot; data-origin-width=&quot;1962&quot; data-origin-height=&quot;826&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;TDS를 사용하는 기존 서비스의 코드를 유지하면서 TDS를 가져올때 HOC가 적용된 로깅 컴포넌트를 사용할 수 있게 해보자&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2194&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqcc0R/btsKdNHPV9z/3YZ3RkWLkmGXFNKV0z7ugK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqcc0R/btsKdNHPV9z/3YZ3RkWLkmGXFNKV0z7ugK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqcc0R/btsKdNHPV9z/3YZ3RkWLkmGXFNKV0z7ugK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdqcc0R%2FbtsKdNHPV9z%2F3YZ3RkWLkmGXFNKV0z7ugK%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;2194&quot; height=&quot;1080&quot; data-origin-width=&quot;2194&quot; data-origin-height=&quot;1080&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;p data-ke-size=&quot;size16&quot;&gt;동일한 이름으로 코드 변경없이 로깅 기능을 제공할 수 있도록&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의존성 트리 자체에서 TDS대신 로깅 라이브러리를 직접 바라보도록 수정해보자&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2086&quot; data-origin-height=&quot;1062&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAJXiw/btsKb0onqyl/KLNLBXCFCIwE6pBEe9FoiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAJXiw/btsKb0onqyl/KLNLBXCFCIwE6pBEe9FoiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAJXiw/btsKb0onqyl/KLNLBXCFCIwE6pBEe9FoiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAJXiw%2FbtsKb0onqyl%2FKLNLBXCFCIwE6pBEe9FoiK%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;2086&quot; height=&quot;1062&quot; data-origin-width=&quot;2086&quot; data-origin-height=&quot;1062&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;p data-ke-size=&quot;size16&quot;&gt;이를 가능하게 하기 위해 yarn berry의 plugin을 이용해보기로 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;yarn(2)은 package manager 자체가 plugin 형태로 구성되어있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2114&quot; data-origin-height=&quot;1080&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w9Vxl/btsKdespUmz/VtgpOkJJIXpuhA4sGPUSnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w9Vxl/btsKdespUmz/VtgpOkJJIXpuhA4sGPUSnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w9Vxl/btsKdespUmz/VtgpOkJJIXpuhA4sGPUSnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw9Vxl%2FbtsKdespUmz%2FVtgpOkJJIXpuhA4sGPUSnk%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;2114&quot; height=&quot;1080&quot; data-origin-width=&quot;2114&quot; data-origin-height=&quot;1080&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;p data-ke-size=&quot;size16&quot;&gt;이에 앞서 yarn의 설치과정을 살펴볼 필요가있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2144&quot; data-origin-height=&quot;1166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AeQKa/btsKcYQP6C9/oG7keZdeYQotB6kpLYN84k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AeQKa/btsKcYQP6C9/oG7keZdeYQotB6kpLYN84k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AeQKa/btsKcYQP6C9/oG7keZdeYQotB6kpLYN84k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAeQKa%2FbtsKcYQP6C9%2FoG7keZdeYQotB6kpLYN84k%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;2144&quot; height=&quot;1166&quot; data-origin-width=&quot;2144&quot; data-origin-height=&quot;1166&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;p data-ke-size=&quot;size16&quot;&gt;- yarn add 시 Resolution step에서 새롭게 설치된 패키지명이 표시가됨&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;618&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QXV8C/btsKbCVN452/zgI44v7RN19Cstkhkgenfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QXV8C/btsKbCVN452/zgI44v7RN19Cstkhkgenfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QXV8C/btsKbCVN452/zgI44v7RN19Cstkhkgenfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQXV8C%2FbtsKbCVN452%2FzgI44v7RN19Cstkhkgenfk%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;1288&quot; height=&quot;618&quot; data-origin-width=&quot;1288&quot; data-origin-height=&quot;618&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. resolution - 버전의 범위 git repo등의 출처를 받은 뒤 하나의 고유 버전을 가리키는 id를 받음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. fetch - resolution에서 얻은 id를 바탕으로 필요한 의존성 다운로드&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. link - 다운로드한 의존성을 어플리케이션에서 사용할 수 있게 연결&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(node moldules에선 필요한 의존성을 복사, pnp환경에선 pnp manifest안에 각각의 패키지 위치를 기입)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2132&quot; data-origin-height=&quot;1134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N5OSv/btsKbB3Ho8w/kNeYF0e3bpSVxyOHUJ1BZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N5OSv/btsKbB3Ho8w/kNeYF0e3bpSVxyOHUJ1BZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N5OSv/btsKbB3Ho8w/kNeYF0e3bpSVxyOHUJ1BZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN5OSv%2FbtsKbB3Ho8w%2FkNeYF0e3bpSVxyOHUJ1BZK%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;2132&quot; height=&quot;1134&quot; data-origin-width=&quot;2132&quot; data-origin-height=&quot;1134&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;p data-ke-size=&quot;size16&quot;&gt;그래서 결론적으로 TDS를 직접가져오는 것이 아닌 해당 패키지가 로깅 패키지를 거치게 하기 위해선&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Resolution step에서 처리해야한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2010&quot; data-origin-height=&quot;1164&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qaw7f/btsKb6BYRCx/1KGGHxJZL1kFpRpRKDEBSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qaw7f/btsKb6BYRCx/1KGGHxJZL1kFpRpRKDEBSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qaw7f/btsKb6BYRCx/1KGGHxJZL1kFpRpRKDEBSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqaw7f%2FbtsKb6BYRCx%2F1KGGHxJZL1kFpRpRKDEBSk%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;2010&quot; height=&quot;1164&quot; data-origin-width=&quot;2010&quot; data-origin-height=&quot;1164&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;p data-ke-size=&quot;size16&quot;&gt;좀더 각 step의 동작 순서를 세부적으로 살펴보자&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2016&quot; data-origin-height=&quot;1196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r6t2p/btsKby69wtP/DpQ9z4JKkXRABXz6gNrAUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r6t2p/btsKby69wtP/DpQ9z4JKkXRABXz6gNrAUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r6t2p/btsKby69wtP/DpQ9z4JKkXRABXz6gNrAUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr6t2p%2FbtsKby69wtP%2FDpQ9z4JKkXRABXz6gNrAUk%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;2016&quot; height=&quot;1196&quot; data-origin-width=&quot;2016&quot; data-origin-height=&quot;1196&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;p data-ke-size=&quot;size16&quot;&gt;tds 버전을 넣을 수 있게 decriptor를 수정하고, 로깅 관련 코드를 대신 resolve할 수 있게&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tds 버전과 로깅의 버전을 각각 독립적으로 관리할 수 있음&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2076&quot; data-origin-height=&quot;1192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHB7PC/btsKckzZjB5/Ohj68DX2dKjKoUmYL7liD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHB7PC/btsKckzZjB5/Ohj68DX2dKjKoUmYL7liD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHB7PC/btsKckzZjB5/Ohj68DX2dKjKoUmYL7liD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHB7PC%2FbtsKckzZjB5%2FOhj68DX2dKjKoUmYL7liD1%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;2076&quot; height=&quot;1192&quot; data-origin-width=&quot;2076&quot; data-origin-height=&quot;1192&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;yarn plugin 기반으로 개발된 환경에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;package.json에서 의존성의 npm 버전 대신 logging으로 시작되는 특수한 버전을 사용할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2110&quot; data-origin-height=&quot;950&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2jcnr/btsKc17L4j1/7hwKYTBmf5Nd5VMPpX8cC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2jcnr/btsKc17L4j1/7hwKYTBmf5Nd5VMPpX8cC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2jcnr/btsKc17L4j1/7hwKYTBmf5Nd5VMPpX8cC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2jcnr%2FbtsKc17L4j1%2F7hwKYTBmf5Nd5VMPpX8cC1%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;2110&quot; height=&quot;950&quot; data-origin-width=&quot;2110&quot; data-origin-height=&quot;950&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;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;2054&quot; data-origin-height=&quot;1170&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dhfK9p/btsKdExriqn/2K7sc9GmOOYe45sklCkNe1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dhfK9p/btsKdExriqn/2K7sc9GmOOYe45sklCkNe1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dhfK9p/btsKdExriqn/2K7sc9GmOOYe45sklCkNe1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdhfK9p%2FbtsKdExriqn%2F2K7sc9GmOOYe45sklCkNe1%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;2054&quot; height=&quot;1170&quot; data-origin-width=&quot;2054&quot; data-origin-height=&quot;1170&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;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;a href=&quot;https://www.youtube.com/watch?v=E7jdKomaqjI&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=E7jdKomaqjI&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/236</guid>
      <comments>https://hmk1022.tistory.com/entry/yarn-plugin%EC%9C%BC%EB%A1%9C-%EC%9A%B0%EC%95%84%ED%95%98%EA%B2%8C-%EB%A1%9C%EA%B9%85%ED%95%98%EA%B8%B0#entry236comment</comments>
      <pubDate>Sun, 20 Oct 2024 09:58:03 +0900</pubDate>
    </item>
    <item>
      <title>프론트엔드의 표준 (HTML, CSS, 크로스브라우징, 브라우저퍼포먼스, 웹 접근성)</title>
      <link>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%9D%98-%ED%91%9C%EC%A4%80-HTML-CSS-%ED%81%AC%EB%A1%9C%EC%8A%A4%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A7%95-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%ED%8D%BC%ED%8F%AC%EB%A8%BC%EC%8A%A4-%EC%9B%B9-%EC%A0%91%EA%B7%BC%EC%84%B1</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;프론트엔드 개발의 중요성&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트엔드프런트엔드 개발은 웹 애플리케이션이나 웹사이트의 &amp;lsquo;얼굴&amp;rsquo;입니다. 사용자가 처음 만나는 부분이기 때문에, 프런트엔드 개발의 품질은 사용자의 첫인상에 직접적인 영향을 미치죠. 하지만 왜 그렇게 중요한 걸까요? 몇 가지 예시를 통해 살펴보겠습니다.&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;512&quot; data-origin-height=&quot;124&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MfApd/btsJRrZxPHX/R6RNU6yJMzisrdlSNLUXlk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MfApd/btsJRrZxPHX/R6RNU6yJMzisrdlSNLUXlk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MfApd/btsJRrZxPHX/R6RNU6yJMzisrdlSNLUXlk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMfApd%2FbtsJRrZxPHX%2FR6RNU6yJMzisrdlSNLUXlk%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;636&quot; height=&quot;154&quot; data-origin-width=&quot;512&quot; data-origin-height=&quot;124&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;p data-ke-size=&quot;size16&quot;&gt;1. 사용자 경험( UX)&lt;br /&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;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;프론트엔드 개발은 브랜드 이미지와 직결됩니다. 많은 스타트업이 초기 단계에서 웹사이트 디자인에 신경을 많이 씁니다. 예를 들어, 애플의 웹사이트는 세련되고 현대적인 디자인으로 유명합니다. 사용자들은 이러한 비주얼에 매료되고, 자연스럽게 브랜드에 대한 신뢰도를 높이게 됩니다. 반면, 디자인이 어지럽고 구식인 웹사이트는 브랜드 신뢰도를 떨어뜨릴 수 있습니다.&lt;/p&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;p data-ke-size=&quot;size16&quot;&gt;프런트엔드 개발은 웹 접근성을 보장하는 데 중요한 역할을 합니다. 모든 사용자가 웹 콘텐츠에 접근할 수 있도록 설계된 웹사이트는 포괄적인 사회를 만드는 데 기여합니다. 예를 들어, 시각장애인을 위한 스크린 리더를 지원하는 웹사이트는 그들이 정보에 접근할 수 있도록 도와줍니다. 이러한 접근성은 단순한 의무를 넘어, 더 많은 사용자가 웹을 이용할 수 있게 만드는 중요한 요소입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고 - &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/Accessibility/Understanding_WCAG&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN 웹 접근성 지침(WCAG)&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&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;브라우저와 OS와 관련 없이 하나의 코드로 모든 플랫폼을 대응할 수 있어&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 검색엔진 최적화(SEO)&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;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 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;더욱이, 웹 접근성은 단순한 선택이 아니라 법적인 책임이 될 수 있습니다. 많은 국가에서 웹사이트 접근성에 대한 법적 요구 사항이 있으며, 이를 준수하지 않으면 소송이나 벌금 등의 법적 문제가 발생할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;HTML 표준&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML(하이퍼텍스트 마크업 언어)은 웹 페이지를 작성하는 데 사용되는 기본적인 언어입니다. HTML 표준은 &lt;b&gt;웹 콘텐츠의 구조와 의미를 정의하며, 시맨틱 웹의 기초가 됩니다.&lt;/b&gt; HTML 표준을 준수하면 웹 페이지가 더 이해하기 쉽고, 접근성 및 SEO(검색 엔진 최적화)에서 유리한 점을 제공합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. HTML의 기본 구조&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML 문서는 다음과 같은 기본 구조를 가집니다:&lt;/p&gt;
&lt;pre id=&quot;code_1727590969622&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&quot;ko&quot;&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&quot;UTF-8&quot;&amp;gt;
    &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&amp;gt;
    &amp;lt;title&amp;gt;HTML 표준 예제&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;header&amp;gt;
        &amp;lt;h1&amp;gt;HTML 표준의 중요성&amp;lt;/h1&amp;gt;
    &amp;lt;/header&amp;gt;
    &amp;lt;main&amp;gt;
        &amp;lt;article&amp;gt;
            &amp;lt;h2&amp;gt;HTML이란?&amp;lt;/h2&amp;gt;
            &amp;lt;p&amp;gt;HTML은 웹 페이지의 구조를 정의하는 마크업 언어입니다.&amp;lt;/p&amp;gt;
        &amp;lt;/article&amp;gt;
        &amp;lt;aside&amp;gt;
            &amp;lt;h3&amp;gt;관련 링크&amp;lt;/h3&amp;gt;
            &amp;lt;ul&amp;gt;
                &amp;lt;li&amp;gt;&amp;lt;a href=&quot;https://www.w3.org/TR/html52/&quot;&amp;gt;W3C HTML 표준&amp;lt;/a&amp;gt;&amp;lt;/li&amp;gt;
            &amp;lt;/ul&amp;gt;
        &amp;lt;/aside&amp;gt;
    &amp;lt;/main&amp;gt;
    &amp;lt;footer&amp;gt;
        &amp;lt;p&amp;gt;&amp;amp;copy; 2024 모든 권리 보유&amp;lt;/p&amp;gt;
    &amp;lt;/footer&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;&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;이 코드에서 보듯이, HTML 문서는 &amp;lt;!DOCTYPE html&amp;gt; 선언으로 시작하며, &amp;lt;html&amp;gt; 요소 내에 &amp;lt;head&amp;gt;와 &amp;lt;body&amp;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;2. 시맨틱 HTML&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시맨틱 HTML은 웹 페이지의 구조와 의미를 명확히 하기 위해 적절한 태그를 사용하는 것입니다. 예를 들어, &amp;lt;header&amp;gt;, &amp;lt;footer&amp;gt;, &amp;lt;article&amp;gt;, &amp;lt;section&amp;gt; 등은 콘텐츠의 의미를 명확히 하여, 브라우저나 검색 엔진이 페이지를 더 잘 이해할 수 있게 도와줍니&lt;/p&gt;
&lt;pre id=&quot;code_1727590990630&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;article&amp;gt;
    &amp;lt;h2&amp;gt;웹 접근성이란?&amp;lt;/h2&amp;gt;
    &amp;lt;p&amp;gt;웹 접근성은 모든 사용자가 웹 콘텐츠에 접근할 수 있도록 하는 것입니다.&amp;lt;/p&amp;gt;
&amp;lt;/article&amp;gt;&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;lt;article&amp;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;3. HTML 표준 준수의 장점&lt;/h4&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;: 시맨틱 태그를 사용하면 스크린 리더와 같은 보조 기술이 콘텐츠를 더 쉽게 이해할 수 있습니다. 예를 들어, alt 속성이 있는 &amp;lt;img&amp;gt; 태그는 시각 장애인이 이미지의 내용을 알 수 있도록 해줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1727591036485&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;img src=&quot;image.jpg&quot; alt=&quot;설명 텍스트&quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; 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;SEO 개선&lt;/b&gt;: 의미 있는 태그 사용은 검색 엔진 크롤러가 페이지를 인덱싱하는 데 도움을 줍니다. 시맨틱 HTML을 활용하면 페이지의 검색 결과 순위를 높일 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;크로스 브라우징&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;크로스 브라우징(Cross-Browsing)은 웹 개발에서 &lt;b&gt;다양한 웹 브라우저와 디바이스에서 웹 페이지가 일관되게 작동하고 표시되도록 보장하는 과정&lt;/b&gt;을 의미합니다. 다양한 브라우저의 엔진 차이로 인해 웹 페이지의 렌더링과 기능이 다르게 나타날 수 있으므로, 크로스 브라우징 문제는 프론트엔드 개발의 중요한 고려 사항입니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 크로스 브라우징 문제의 원인&lt;/h4&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;: 각 브라우저는 HTML, CSS, JavaScript를 해석하고 렌더링하는 방식이 다릅니다. 예를 들어, Chrome, Firefox, Safari, Edge 등은 동일한 코드를 다르게 해석할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CSS 및 JavaScript 지원 차이&lt;/b&gt;: 특정 CSS 속성이나 JavaScript API가 모든 브라우저에서 지원되지 않을 수 있습니다. 이러한 차이로 인해 웹 페이지의 스타일과 동작이 일관되지 않을 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;뷰포트 및 반응형 문제&lt;/b&gt;: 다양한 화면 크기와 해상도에 맞춰 레이아웃을 조정해야 할 때, 브라우저마다 반응형 처리 방식이 다를 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 현대 프론트엔드의 해결 방안&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현대 프론트엔드 개발에서는 여러 가지 방법으로 크로스 브라우징 문제를 해결하고 있습니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;CSS 리셋 및 노멀라이즈 사용&lt;/b&gt;: 기본 스타일을 초기화하거나 표준화하기 위해 CSS 리셋(CSS Reset)이나 노멀라이즈(Normalize.css)를 사용합니다. 이는 각 브라우저에서 기본적으로 제공하는 스타일 차이를 줄이는 데 도움을 줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727591362549&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* Normalize.css의 예시 */
html {
    line-height: 1.15; /* Improved line height */
}&lt;/code&gt;&lt;/pre&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;모던 CSS와 JavaScript 프레임워크 사용&lt;/b&gt;: React, Vue.js, Angular와 같은 프레임워크는 크로스 브라우징 문제를 내재적으로 해결하는 기능을 제공합니다. 예를 들어, 이러한 프레임워크는 다양한 브라우저에서 일관되게 작동하는 컴포넌트 기반의 UI를 제공합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Polyfill과 Babel 사용&lt;/b&gt;: 최신 JavaScript 기능을 사용하더라도 구형 브라우저에서 문제가 발생하지 않도록 Polyfill을 사용하여 기능을 추가하거나, Babel과 같은 도구를 사용해 ES6+ 코드를 ES5로 변환하여 더 많은 브라우저에서 호환되도록 합니다&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;Babel을 통한 트랜스파일링 예시&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 트랜스파일링 before&lt;/p&gt;
&lt;pre id=&quot;code_1727591469265&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// arrowFunction.js
const add = (a, b) =&amp;gt; a + b;

class Person {
    constructor(name) {
        this.name = name;
    }

    greet() {
        console.log(`Hello, my name is ${this.name}`);
    }
}

const john = new Person('John');
john.greet();&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;- 트랜스파일링 after&lt;/p&gt;
&lt;pre id=&quot;code_1727591485912&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// arrowFunction-compiled.js
&quot;use strict&quot;;

var add = function add(a, b) {
    return a + b;
};

var Person = function () {
    function Person(name) {
        this.name = name;
    }

    Person.prototype.greet = function greet() {
        console.log(&quot;Hello, my name is &quot; + this.name);
    };

    return Person;
}();

var john = new Person('John');
john.greet();&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;i&gt; polyfill 예시&lt;br /&gt;&lt;br /&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Array.prototype.includes Polyfill&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Array.prototype.includes 메서드는 ES2015에서 추가된 기능으로, 배열에 특정 요소가 포함되어 있는지 확인합니다. 이 메서드를 지원하지 않는 브라우저에서 사용할 수 있도록 Polyfill을 추가할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1727592637334&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Array.prototype.includes Polyfill
if (!Array.prototype.includes) {
    Array.prototype.includes = function (value) {
        return this.indexOf(value) !== -1;
    };
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 Polyfill은 Array.prototype.includes가 존재하지 않을 경우, indexOf 메서드를 사용하여 주어진 값이 배열에 포함되어 있는지 확인합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- fetch polyfill&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;fetch API는 네트워크 요청을 수행할 때 사용되며, 이를 지원하지 않는 브라우저를 위해 whatwg-fetch 라이브러리를 사용하여 Polyfill을 적용할 수 있습니다. 이 라이브러리는 GitHub에서 제공하며, 간단하게 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1727592669880&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- HTML에서 Fetch Polyfill을 사용하기 위한 CDN 링크 --&amp;gt;
&amp;lt;script src=&quot;https://cdnjs.cloudflare.com/ajax/libs/fetch/3.0.0/fetch.min.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 HTML 파일에 추가하면 fetch 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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 밖에도 &lt;a href=&quot;https://caniuse.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;can i use&lt;/a&gt;에서 특정 css나 api 등이 어떤 브라우저에서 지원 되는지 확인 할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;브라우저 퍼포먼스&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 브라우저 성능의 중요성&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;: 빠른 로딩 시간과 원활한 상호작용은 사용자 경험에 큰 영향을 미칩니다. 느린 페이지는 사용자의 이탈률을 증가시키고, 브랜드에 대한 신뢰도를 낮출 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;SEO&lt;/b&gt;: 검색 엔진 최적화(SEO)에도 브라우저 성능이 중요한 역할을 합니다. Google은 페이지 속도를 중요한 순위 요소 중 하나로 간주하며, 느린 웹 페이지는 검색 결과에서 더 낮은 순위를 받을 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;전환율&lt;/b&gt;: 전자상거래 웹사이트의 경우, 페이지 로딩 속도가 전환율에 직접적인 영향을 미칩니다. 페이지가 느릴수록 고객이 구매를 완료할 가능성이 줄어듭니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 브라우저 성능 개선 전략&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. 리소스 최적화&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;: 이미지 크기를 줄이고, WebP와 같은 최신 형식을 사용하여 페이지 로딩 속도를 개선합니다. 또한, 이미지에 대한 지연 로딩(lazy loading)을 적용하여 사용자가 필요할 때만 로드하도록 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727592778246&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;img src=&quot;example.jpg&quot; loading=&quot;lazy&quot; alt=&quot;Example Image&quot;&amp;gt;&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;b&gt;&lt;br /&gt;&lt;/b&gt;요즘 많이 쓰이는 Next.js의 경우는 이미지 최적화를 위한 내장 컴포넌트를 제공합니다. 이 컴포넌트를 사용하면 자동으로 크기 조정, WebP 포맷 지원, 그리고 지연 로딩을 구현할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1727592895356&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import Image from 'next/image';

const MyImage = () =&amp;gt; (
    &amp;lt;Image src=&quot;/image.jpg&quot; alt=&quot;My Image&quot; width={500} height={300} /&amp;gt;
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&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;CSS 및 JavaScript 압축&lt;/b&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;: CSS 및 JavaScript 파일을 압축하여 파일 크기를 줄이고, 다운로드 속도를 개선합니다. 여러 파일을 하나의 파일로 병합하여 HTTP 요청 수를 줄이는 것도 좋은 방법입니다.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 비동기 로딩&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;JavaScript 비동기 로딩&lt;/b&gt;: async 또는 defer 속성을 사용하여 스크립트를 비동기적으로 로드하여 페이지의 렌더링 차단을 방지합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727592824011&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script src=&quot;script.js&quot; async&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 캐싱 활용&lt;/p&gt;
&lt;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;: HTTP 캐싱을 설정하여 사용자가 페이지를 다시 방문할 때 리소스를 로컬에 저장된 캐시에서 불러올 수 있도록 합니다. 이를 통해 서버 요청을 줄이고 로딩 시간을 단축할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1727592935066&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Cache-Control: public, max-age=31536000&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;요즘 많이 쓰이는&lt;span&gt; react-query는 클라이언트 측 데이터 fetching 및 caching을 관리하기 위한 강력한 도구로, 웹 애플리케이션의 성능을 최적화하는 데 매우 유용합니다.&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; text-align: start;&quot;&gt;&lt;span&gt;코드 예시&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1727593009905&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import React from 'react';
import { useQuery } from '@tanstack/react-query';

const fetchUsers = async () =&amp;gt; {
    const response = await fetch('https://jsonplaceholder.typicode.com/users');
    if (!response.ok) {
        throw new Error('Network response was not ok');
    }
    return response.json();
};

const UserList = () =&amp;gt; {
    const { data, error, isLoading } = useQuery(['users'], fetchUsers, {
        staleTime: 5000, // 5초 동안 데이터가 신선하다고 간주
        cacheTime: 10000, // 10초 동안 캐시된 데이터가 유지
    });

    if (isLoading) return &amp;lt;div&amp;gt;Loading...&amp;lt;/div&amp;gt;;
    if (error) return &amp;lt;div&amp;gt;Error fetching data: {error.message}&amp;lt;/div&amp;gt;;

    return (
        &amp;lt;ul&amp;gt;
            {data.map(user =&amp;gt; (
                &amp;lt;li key={user.id}&amp;gt;{user.name}&amp;lt;/li&amp;gt;
            ))}
        &amp;lt;/ul&amp;gt;
    );
};

export default UserList;&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;fetchUsers 함수&lt;/b&gt;: 이 함수는 사용자의 데이터를 API에서 가져오는 비동기 함수입니다. 에러 처리를 포함하여 네트워크 요청을 수행합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;useQuery 훅&lt;/b&gt;: 이 훅은 데이터를 fetching하고 상태를 관리하는 데 사용됩니다. 첫 번째 인자로 쿼리 키를 전달하고, 두 번째 인자로 데이터를 fetching할 함수를 전달합니다. 선택적 인자로는 캐싱 전략을 설정할 수 있습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;staleTime: 데이터를 신선하다고 간주하는 시간 (밀리초 단위)입니다. 이 시간 동안은 같은 쿼리를 다시 요청하지 않습니다.&lt;/li&gt;
&lt;li&gt;cacheTime: 쿼리의 캐시된 데이터를 유지하는 시간입니다. 이 시간이 지나면 캐시된 데이터가 제거됩니다.&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;style7&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&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;프론트엔드 표준 준수는 웹 개발의 핵심입니다. HTML과 CSS의 올바른 사용은 일관된 사용자 경험을 제공하며, 크로스 브라우징을 통해 다양한 환경에서도 접근성을 보장합니다.&lt;/p&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/Accessibility/Understanding_WCAG&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.mozilla.org/ko/docs/Web/Accessibility/Understanding_WCAG&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727593206248&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;웹 컨텐츠 접근성 지침 이해하기 - 접근성 | MDN&quot; data-og-description=&quot;이 문서에서는 W3C 웹 컨텐츠 접근성 지침 2.0 또는 2.1(이 글에서는 WCAG)에 설명된 권장 사항들을 준수하기 위한 단계들을 이해하는 데에 도움이 되는 간략한 설명을 제공합니다.&quot; data-og-host=&quot;developer.mozilla.org&quot; data-og-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/Accessibility/Understanding_WCAG&quot; data-og-url=&quot;https://developer.mozilla.org/ko/docs/Web/Accessibility/Understanding_WCAG&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/s7Mm1/hyXaxMk07W/Zkg5P6yD5l4Q9Iij2Ioxb1/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/Accessibility/Understanding_WCAG&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/Accessibility/Understanding_WCAG&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/s7Mm1/hyXaxMk07W/Zkg5P6yD5l4Q9Iij2Ioxb1/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080');&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;웹 컨텐츠 접근성 지침 이해하기 - 접근성 | MDN&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 문서에서는 W3C 웹 컨텐츠 접근성 지침 2.0 또는 2.1(이 글에서는 WCAG)에 설명된 권장 사항들을 준수하기 위한 단계들을 이해하는 데에 도움이 되는 간략한 설명을 제공합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.mozilla.org&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>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/235</guid>
      <comments>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%9D%98-%ED%91%9C%EC%A4%80-HTML-CSS-%ED%81%AC%EB%A1%9C%EC%8A%A4%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A7%95-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%ED%8D%BC%ED%8F%AC%EB%A8%BC%EC%8A%A4-%EC%9B%B9-%EC%A0%91%EA%B7%BC%EC%84%B1#entry235comment</comments>
      <pubDate>Sun, 29 Sep 2024 16:04:11 +0900</pubDate>
    </item>
    <item>
      <title>WebRTC의 동작원리</title>
      <link>https://hmk1022.tistory.com/entry/WebRTC%EC%9D%98-%EB%8F%99%EC%9E%91%EC%9B%90%EB%A6%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;WebRTC(Web Real-Time Communication)은 &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;&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;b&gt;실시간 통신&lt;/b&gt;: 브라우저 간에 실시간으로 오디오, 비디오, 데이터 스트림을 주고받습니다.(기본적으로 UDP 사용)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;플러그인 불필요&lt;/b&gt;: 별도의 설치나 플러그인이 필요 없으며, HTML5와 자바스크립트만으로 통신이 가능합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;P2P 연결&lt;/b&gt;: 서버를 통해 데이터를 중계하지 않고, 사용자들끼리 직접 통신하여 &lt;b&gt;지연 시간&lt;/b&gt;을 최소화합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안&lt;/b&gt;: 기본적으로 모든 통신은 암호화되어 있어, 보안이 중요한 실시간 통신에 적합합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중개서버를 거치지 않기 때문에 빠른 속도로 통신이 가능하며 HTTPS 사용이 강제되기 때문에 보안 또한 보장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;속도와 보안과 더불어 WebRTC가 다양한 플랫폼, 브라우저에서 같은 사용자 경험을 제공하기 위해 호환성 또한 고려되어야 합니다.&lt;/p&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;a href=&quot;https://caniuse.com/?search=webrtc&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;can i use&lt;/a&gt;에서 확인 가능하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1156&quot; data-origin-height=&quot;511&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dpnBxK/btsJLvVsxnK/iM5JlbkchVfdREhERu9e9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dpnBxK/btsJLvVsxnK/iM5JlbkchVfdREhERu9e9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dpnBxK/btsJLvVsxnK/iM5JlbkchVfdREhERu9e9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdpnBxK%2FbtsJLvVsxnK%2FiM5JlbkchVfdREhERu9e9K%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;1156&quot; height=&quot;511&quot; data-origin-width=&quot;1156&quot; data-origin-height=&quot;511&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;WebRTC 자체는 1.0의 표준 버전이 있지만, 이 규격을 모두 준수하는 플랫폼이 많지 않은 것 같네요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 각 브라우저 WebRTC API에는 moz, webkit 같은 벤더 프리픽스가 붙어 있습니다.&lt;/p&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;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/WebRTC_API&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN 문서&lt;/a&gt;에 따르면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 브라우저마다 다른 코덱 및 기타 미디어 기능에 대한 지원 수준이 다르기 때문에, 코드 작성 전에 Google에서 제공하는&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;shim 및 polyfill을 사용하여 다양한 플랫폼의 WebRTC 구현 간의 차이점을 없애주는&lt;/b&gt;&amp;nbsp;&lt;a href=&quot;https://github.com/webrtcHacks/adapter&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Adapter.js&lt;/a&gt; 라이브러리를 사용하는 것을 강력하게 권장하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;WebRTC의 동작원리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;P2P란(Peer to Peer)?&lt;/h4&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: #fafafa; color: #333333; text-align: start;&quot;&gt;**P2P (Peer-to-Peer)**는&lt;/span&gt;&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;네트워크에서 중앙 서버 없이, 각 참여자가 동등한 권한을 가지고 직접적으로 데이터를 주고받는 통신 방식&lt;/b&gt;&lt;span style=&quot;background-color: #fafafa; color: #333333; text-align: start;&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;h4 data-ke-size=&quot;size20&quot;&gt;P2P 절차&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebRTC는 P2P 방싱의 커뮤니케이션이기 때문에 통신 대상인 각각의 웹 브라우저는 다음과 같은 절차를 밟아야 한다.&lt;/p&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. 각 클라이언트가 P2P 연결에 동의&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 2번과 3번 단계가 일반적인 통신 방법으로는 이해하기 어려운 부분이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저는 웹 서버가 아니기 때문에 외부에서 접근할 수 없는 주소가 없기 때문에 WebRTC가 P2P 기반이긴 하지만&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;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;방화벽과 NAT 트래버셜&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 컴퓨터에는 공인 IP가 할당되어 있지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통의 회사 사무실에선 건물의 스위치(&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;NAT&lt;/span&gt;)등을 이용해 공유기에 사설 IP를 받아 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(건물의 NAT &amp;gt; 사무실 공유기 NAT &amp;gt; 내 PC)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;871&quot; data-origin-height=&quot;323&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6bf2h/btsJLgjRivn/LQ3WNMKLeSC189yxSPeqKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6bf2h/btsJLgjRivn/LQ3WNMKLeSC189yxSPeqKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6bf2h/btsJLgjRivn/LQ3WNMKLeSC189yxSPeqKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6bf2h%2FbtsJLgjRivn%2FLQ3WNMKLeSC189yxSPeqKK%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;798&quot; height=&quot;296&quot; data-origin-width=&quot;871&quot; data-origin-height=&quot;323&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;p data-ke-size=&quot;size16&quot;&gt;일반 컴퓨터에 공인 IP가 할당되지 않는 이유&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&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;공인 IP&lt;/b&gt;는 인터넷에 직접 연결되는 고유한 주소이며, &lt;b&gt;사설 IP&lt;/b&gt;는 내부 네트워크에서만 사용되는 주소입니다.&lt;/li&gt;
&lt;li&gt;일반적인 컴퓨터에 공인 IP가 할당되지 않는 이유는 IP 주소의 부족, 보안, 네트워크 관리의 용이성, 비용 등의 이유 때문입니다. 사설 IP를 사용하여 NAT를 통해 공인 IP를 공유함으로써 이러한 문제를 해결하고 있습니다.&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;예시로 회사 사무실 공유기의 IP 할당에 대해 설명해 보겠습니다.&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;b&gt;건물 전체의 라우터&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;건물 자체에 위치한 라우터가 ISP로부터 공인 IP 주소를 할당받습니다. 이 라우터는 건물의 모든 사무실에 인터넷 연결을 제공합니다.&lt;/li&gt;
&lt;li&gt;각 사무실은 건물의 라우터에 연결되며, 이를 통해 인터넷에 접근합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사무실의 공유기&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사무실 내의 공유기는 일반적으로 &lt;b&gt;사설 IP 주소&lt;/b&gt;를 할당받습니다. 이 경우 공유기는 건물의 라우터와 연결되어 있으며, 건물의 라우터에서 할당받은 공인 IP를 사용하여 인터넷에 연결됩니다.&lt;/li&gt;
&lt;li&gt;공유기는 사무실 내부의 장치(컴퓨터, 프린터 등)에게 사설 IP 주소를 할당하여, 내부 네트워크를 구성하고 인터넷 접속을 관리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;NAT의 역할&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 경우, &lt;b&gt;NAT&lt;/b&gt;는 두 번 적용됩니다:
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;건물의 라우터&lt;/b&gt;: 건물의 공인 IP와 내부 네트워크의 사설 IP 간의 변환을 관리합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사무실의 공유기&lt;/b&gt;: 사무실의 사설 IP와 건물의 공인 IP 간의 변환을 관리합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&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;b&gt;공유기가 직접 공인 IP를 할당받지 않고&lt;/b&gt;, 건물의 라우터가 공인 IP를 할당받아 여러 사무실에 인터넷을 제공하는 구조가 가능합니다.&lt;/li&gt;
&lt;li&gt;이 경우 각 사무실의 공유기는 사설 IP를 사용하여 내부 장치를 관리하고, 건물의 라우터를 통해 인터넷에 연결됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 라우터가 NAT 역할을 합니다. 외부에서 접근하는 공인 IP와 포트 번호를 확인하여 현재 네트워크 내의 사설 IP 들을 적절히 매핑시켜 줍니다.&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;결론적으로 어떤 브라우저 두 개가 직접 통신하려면, 각자 현재 연결된 라우터의 공인 IP 주소와 포트 번호를 먼저 알아내야 합니다.&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;But, 어떤 라우터들은 특정 주소나 포트와 연결을 차단하는 방화벽이 설정되어 있을 수도 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 라우터를 통과해서 연결할 방법을 찾아내는 과정을 &lt;a href=&quot;https://en.wikipedia.org/wiki/NAT_traversal&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;NAT 트래버셜&lt;/a&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: #9d9d9d;&quot;&gt;Traversal - 가로지르는, 여기저기 돌아다니는&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;STUN &amp;amp; TURN&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;299&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UFCEg/btsJLJzb2Fu/OetkbK8dsy4lztMaaqlJO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UFCEg/btsJLJzb2Fu/OetkbK8dsy4lztMaaqlJO1/img.png&quot; data-alt=&quot;STUN vs TURN&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UFCEg/btsJLJzb2Fu/OetkbK8dsy4lztMaaqlJO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUFCEg%2FbtsJLJzb2Fu%2FOetkbK8dsy4lztMaaqlJO1%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;299&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;299&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;STUN vs TURN&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NAT 트래버셜 작업은 STUN(Session Traversal Utilitise for NAT) 서버에 의해 이루어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;STUN 방식은 &lt;b&gt;단말이 자신의 공인 IP주소와 포트를 확인하는 과정에 대한 프로토콜입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, STUN 서버는 인터넷의 복잡한 주소들 사이에 유일하게 자신을 식별할 수 있는 정보를 반환해 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebRTC 연결을 시작하기 전에 STUN 서버를 향해 요청을 보내면 STUN 서버는 NAT 뒤에 있는 Peer들이 서로 연결할 수 있도록 공인 IP와 포트를 찾아줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;But, STUN 서버를 이용하더라도 항상 자신의 정보를 알아낼 수는 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 라우터들은 방화벽 정책을 다르게 할 수도 있고, 이전에 연결된 네트워크만 연결할 수 있게 제한을 걸기도 합니다.(Symmetric NAT)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때문에 STUN 서버를 통해 자기 자신의 주소를 찾아내지 못했을 경우, TURN(Traversal Using Relay NAT)&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;TURN 방식은 &lt;b&gt;네트워크 미디어를 중개하는 서버를 이용하는 방식&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간에 서버를 한 번 거치기 때문에 엄밀히 말하면 P2P 방식이 아니게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 보안정책이 엄격한 개인 NAT 내부에 위치한 브라우저와 P2P 통신을 할 수 있는 유일한 방법이 기 때문에&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;ICE와 Candidate&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 이야기한 STUN, TURN 서버를 이용해 획득한 IP 주소와 프로토콜, 포트의 조합으로 구성 연결 가능한&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주소들은 후보(Candidate)라고 부릅니다. 그리고 이 과정을 후보 찾기(Finding Candidate)라고 부릅니다.&lt;/p&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;p data-ke-size=&quot;size16&quot;&gt;- 자신의 사설 IP와 포트 넘버&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 자신의 공인 IP와 포트넘버(STUN, TURN 서버로부터 획득 가능)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- TURN 서버의 IP와 포트 넘버(TURN 서버로부터 획득 가능)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 모든 과정들을 ICE(Interactive Connectivity Establishment)라는 프레임 워크 위에서 이뤄집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ICE는 두 개의 단말이 P2P 연결을 가능하게 하도록 최적의 경로를 찾아주는 프레임워크입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 내용을 요약하면 ICE 프레임워크가 STUN 혹은 TURN 서버를 이용해 상대방과 연결 가능한 후보들을 갖고 있고,&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt; SDP&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1052&quot; data-origin-height=&quot;405&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cWXC6h/btsJKGwWtsf/ZxkCdGMka4kediEmnjAq6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cWXC6h/btsJKGwWtsf/ZxkCdGMka4kediEmnjAq6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cWXC6h/btsJKGwWtsf/ZxkCdGMka4kediEmnjAq6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcWXC6h%2FbtsJKGwWtsf%2FZxkCdGMka4kediEmnjAq6k%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;1052&quot; height=&quot;405&quot; data-origin-width=&quot;1052&quot; data-origin-height=&quot;405&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;SDP(Session Description Protocol)은 WebRTC에서 스트리밍 미디어의 해상도, 코텍 등의 멀티미디어 컨텐츠의 초기 인수를 설명하기위해 채택한 프로토콜입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미디어와 관련된 초기 세팅 정보를 기술하는 SDP는 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%B0%9C%ED%96%89-%EA%B5%AC%EB%8F%85_%EB%AA%A8%EB%8D%B8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;발행 구독 모델(Pub/Sub)&lt;/a&gt;과 유사한 제안 응답 모델(Offer/Answer)을 가지게 됩니다.&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;size16&quot;&gt;응답을 받게되면 각자 피어가 수집한 ICE 후보 중에서 최적의 경로를 설정하고 협상하는 프로세스가 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수집한 ICE 후보들로 패킷을 보내 가장 먼저 지연 시간이 적고 안정적인 경로를 탐색합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 최적의 ICE 후보가 선택되면, 기본적으로 필요한 모든 메타 데이터와 IP 주소 및 포트, 미디어 정보가 피어 간 합의가 완료됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Trickle&amp;nbsp;ICE&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ICE 프레임워크를 설정할 때 자주 접하는 옵션 중 하나가 &lt;b&gt;Trickle ICE&lt;/b&gt;입니다. 이 용어가 어떤 의미인지 짐작이 가시나요?&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 각 피어는 ICE 후보를 수집하여 목록을 완성한 후 한꺼번에 교환합니다. &lt;br /&gt;그러나 이 방식은 SDP의 제안 응답 모델과 맞물려 몇 가지 단점이 있습니다. 후보를 모으는 데 시간이 오래 걸리고, 네트워크 환경에 따라 지연이 발생할 수 있습니다. 또한 한쪽 피어의 ICE 후보 수집이 완료되어야 다른 피어가 후보를 모을 수 있어 비효율적입니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Trickle ICE&lt;/b&gt;는 이러한 비효율적인 후보 교환을 병렬 프로세스로 수행할 수 있게 해주는 기술입니다. &lt;b&gt;즉, 두 개의 피어가 ICE 후보를 수집하고 교환하는 과정을 동기적에서 비동기적으로 변화시킵니다.&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Trickle 옵션이 활성화된 ICE 프레임워크는 각 피어에서 ICE 후보를 발견하는 즉시 교환을 시작합니다. &lt;br /&gt;이를 통해 서로 연결 가능한 ICE를 더 빨리 찾아낼 수 있습니다. 이 옵션 덕분에 ICE 프레임워크는 피어 간의 연결 상태를 체크하면서 연결 시간을 최적화할 수 있습니다. 결론적으로 Trickle 옵션은 활성화하는 것이 좋습니다.&lt;/p&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; &lt;b&gt;Trickle ICE는 후보 수집 과정을 병렬적으로 처리하여, 각 피어가 발견한 ICE 후보를 즉시 교환&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&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;위에서 언급한 모든 과정을 시그널링(Signaling)이라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 &lt;b&gt;RTCPeerConnection 통신에 필요한 프로토콜, 채널, 미디어 코덱 및 형식, 데이터 전송 방법, 라우팅 정보, NAT 통과 방법 등의 통신 규격을 교환하기 위해 두 장치 간의 제어 정보를 주고받는 과정&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;시그널링은 WebRTC 자체에서 지원하는 기능이 아니며, 연결 전 미리 준비해야 하는 과정입니다. 또한 WebRTC의 스펙에 포함되어 있지 않아 정해진 방법이 없습니다. 이는 알 수 없는 두 장치가 언제 어떤 방식으로 연결될지 예측할 수 없기 때문이며, 개발자는 자신에게 맞는 최적의 방법을 선택할 수 있습니다.&lt;/p&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;시그널링 서버를 직접 구축할 경우, 웹 소켓(WebSocket)이나 서버 전송 이벤트(Server-sent Event) 방식을 사용할 수 있습니다.&lt;/p&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를 만들고 브라우저에서 주기적으로 XHR 요청을 통해 폴링(polling) 기법을 적용할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebRTC를 처음 접하는 개발자에게는 표준이 없다는 점이 혼란을 줄 수 있습니다. 직접 서버를 구축하는 것은 작업량이 많기 때문에, 시그널링 서버를 제공하는 솔루션을 사용하는 것도 좋은 방법입니다. 예를 들어, 아마존의 Kinesis Video Stream이나 구글의 AppRTC에서 Google App Engine으로 구현된 시그널링 서버를 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;b&gt;References&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;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/WebRTC_API&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.mozilla.org/ko/docs/Web/API/WebRTC_API&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727226962881&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;WebRTC API - Web API | MDN&quot; data-og-description=&quot;WebRTC(Web Real-Time Communication)은 웹 애플리케이션과 사이트가 중간자 없이 브라우저 간에 오디오나 영상 미디어를 포착하고 마음대로 스트림할 뿐 아니라, 임의의 데이터도 교환할 수 있도록 하는 &quot; data-og-host=&quot;developer.mozilla.org&quot; data-og-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/API/WebRTC_API&quot; data-og-url=&quot;https://developer.mozilla.org/ko/docs/Web/API/WebRTC_API&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cOIJXx/hyW6BCfDqv/buN6g5K7ANduXD9tgVNSy0/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/WebRTC_API&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/API/WebRTC_API&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cOIJXx/hyW6BCfDqv/buN6g5K7ANduXD9tgVNSy0/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080');&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;WebRTC API - Web API | MDN&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;WebRTC(Web Real-Time Communication)은 웹 애플리케이션과 사이트가 중간자 없이 브라우저 간에 오디오나 영상 미디어를 포착하고 마음대로 스트림할 뿐 아니라, 임의의 데이터도 교환할 수 있도록 하는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.mozilla.org&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;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://wormwlrm.github.io/2021/01/24/Introducing-WebRTC.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://wormwlrm.github.io/2021/01/24/Introducing-WebRTC.html&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1727226953363&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;WebRTC는 어떻게 실시간으로 데이터를 교환할 수 있을까? - 재그지그의 개발 블로그&quot; data-og-description=&quot;WebRTC 연결 절차에 대해 알아보고, 이 과정에서 접할 수 있는 낯선 용어들에 대해 정리해봅니다.&quot; data-og-host=&quot;wormwlrm.github.io&quot; data-og-source-url=&quot;https://wormwlrm.github.io/2021/01/24/Introducing-WebRTC.html&quot; data-og-url=&quot;https://wormwlrm.github.io/2021/01/24/Introducing-WebRTC.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/W0KYv/hyW6A4oxux/ArzHTp3nuvV03xnRd2nlW1/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cbfvVU/hyW6COHOSB/Cbxfjy68gdb2DC8kjcp220/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/FMLO0/hyW6ADjOuO/mRyX2hKKLurhehCXStOsN0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://wormwlrm.github.io/2021/01/24/Introducing-WebRTC.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://wormwlrm.github.io/2021/01/24/Introducing-WebRTC.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/W0KYv/hyW6A4oxux/ArzHTp3nuvV03xnRd2nlW1/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cbfvVU/hyW6COHOSB/Cbxfjy68gdb2DC8kjcp220/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/FMLO0/hyW6ADjOuO/mRyX2hKKLurhehCXStOsN0/img.jpg?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&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;WebRTC는 어떻게 실시간으로 데이터를 교환할 수 있을까? - 재그지그의 개발 블로그&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;WebRTC 연결 절차에 대해 알아보고, 이 과정에서 접할 수 있는 낯선 용어들에 대해 정리해봅니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;wormwlrm.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>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/234</guid>
      <comments>https://hmk1022.tistory.com/entry/WebRTC%EC%9D%98-%EB%8F%99%EC%9E%91%EC%9B%90%EB%A6%AC#entry234comment</comments>
      <pubDate>Wed, 25 Sep 2024 11:17:46 +0900</pubDate>
    </item>
    <item>
      <title>프론트엔드의 역사</title>
      <link>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%9D%98-%EC%97%AD%EC%82%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;3년 차 프런트엔드 개발자로서, 요즘 많은 개발자들이 사용하는 React와 Next.js 같은 프레임워크를 나도 사용하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다 문득, 내가 현재 쓰고 있는 기술 스택들이 왜 등장하게 되었는지, 그리고 어떤 문제를 해결하거나 개선했기에 지금까지 널리 사용되고 있는지 궁금해졌다. (재미있게도, 일부는 과거 방식으로 되돌아가는 것처럼 보이기도 한다.)&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고로, 이 글에서는 WEB 1.0이나 IE 등장 등 웹의 초기 역사보다는, JSP 등의 백엔드 중심 개발에서 프런트엔드 직군이 본격적으로 생겨난 시점부터 이야기를 시작해 보려고 합니다.&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;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; 웹 개발 초기에는 프런트엔드와 백엔드의 경계가 불분명했습니다. JSP, PHP, ASP 같은 서버 사이드 기술을 사용해 서버에서 HTML을 렌더링하고 이를 클라이언트에 전달하는 방식이 주류였습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사용자 경험(UX)의 중요성 대두:&lt;/b&gt; 웹이 점점 더 복잡해지면서 사용자 인터랙션의 중요성이 강조되었고, 더 나은 사용자 경험을 제공할 필요가 생기면서 프론트엔드 개발이 전문 분야로 발전하기 시작했습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;AJAX의 등장과 동적 웹페이지:&lt;/b&gt; AJAX가 등장하면서 페이지 전체를 다시 로드하지 않고도 서버와 데이터를 주고받는 비동기 처리가 가능해졌습니다. 이로 인해 웹 애플리케이션은 더욱 동적이고 사용자 친화적인 방식으로 발전할 수 있었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;jQuery와 그 한계&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;DOM 조작의 편리함:&lt;/b&gt; jQuery는 JavaScript로 DOM을 쉽게 조작할 수 있는 라이브러리로, 복잡한 크로스 브라우저 이슈를 해결하며 큰 인기를 끌었습니다.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상태 관리의 어려움:&lt;/b&gt; 하지만 프로젝트가 커질수록 DOM 조작과 상태 관리는 점점 복잡해졌고, 이로 인해 코드의 유지보수성이 떨어졌습니다. 특히 데이터를 관리하고 이를 UI에 일관되게 반영하는 것이 큰 문제였습니다.&lt;br /&gt;이와 더불러 javascript 자체 DOM 조작 API도 점점 발전해 굳이 사용할 필요가 없어지기도 한 것 같다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1377&quot; data-origin-height=&quot;563&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OKfCO/btsJInwoLk0/Q0tkJz4Kht7ViMWJgWSZs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OKfCO/btsJInwoLk0/Q0tkJz4Kht7ViMWJgWSZs1/img.png&quot; data-alt=&quot;하지만 jQuery는 여전히 리액트 다음으로 인기가 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OKfCO/btsJInwoLk0/Q0tkJz4Kht7ViMWJgWSZs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOKfCO%2FbtsJInwoLk0%2FQ0tkJz4Kht7ViMWJgWSZs1%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;1377&quot; height=&quot;563&quot; data-origin-width=&quot;1377&quot; data-origin-height=&quot;563&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;하지만 jQuery는 여전히 리액트 다음으로 인기가 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;AngularJS: 프레임워크의 시작 (2010년)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AngularJS&lt;/b&gt;는 구글에서 2010년에 출시한 프레임워크로, 기존의 jQuery로 해결하기 어려운 대규모 애플리케이션의 복잡한 로직과 데이터 관리를 해결하기 위해 만들어졌습니다. (사실상 MVVM 패턴을 사용하는 것 같지만 앵귤러 공식사이트는 MVW(whatever)라고 표현한다.)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;489&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vNDVc/btsJHsk9V0c/tDo3NhI2R6FXz9EVES4KlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vNDVc/btsJHsk9V0c/tDo3NhI2R6FXz9EVES4KlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vNDVc/btsJHsk9V0c/tDo3NhI2R6FXz9EVES4KlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvNDVc%2FbtsJHsk9V0c%2FtDo3NhI2R6FXz9EVES4KlK%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;418&quot; height=&quot;330&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;489&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;양방향 데이터 바인딩 (Two-way Data Binding):&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;AngularJS는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;양방향 데이터 바인딩&lt;/b&gt;을 도입하여, 모델(데이터)과 뷰(UI)가 자동으로 동기화되었습니다. 즉, 데이터가 변경되면 UI가 자동으로 업데이트되고, UI의 변화도 데이터에 즉시 반영됩니다. 이 기능은 개발 생산성을 크게 향상했습니다.&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;개선점:&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;AngularJS는 jQuery의 단순한 DOM 조작 방식을 넘어서,&lt;b&gt; 애플리케이션 전체의 구조를 체계적으로 관리할 수 있는&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;프레임워크&lt;/b&gt;로 개발되었습니다. 데이터와 UI의 일관성을 자동으로 유지하고, 대규모 애플리케이션에서도 쉽게 확장할 수 있도록 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;React의 등장: 컴포넌트 기반 개발&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Virtual DOM과 컴포넌트 기반 아키텍처:&lt;/b&gt; Facebook에서 개발한 React는 Virtual DOM을 도입하여 DOM 조작의 성능 문제를 해결하고, 컴포넌트 기반 아키텍처를 통해 UI를 모듈화 했습니다. (가상돔이 항상 효율적이라고 볼 순 없다.)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;효율적인 상태 관리:&lt;/b&gt; React의 상태 관리 시스템은 데이터가 변경될 때마다 UI를 효율적으로 업데이트할 수 있게 했습니다. 이를 통해 대형 애플리케이션에서도 일관된 UI와 상태 관리를 할 수 있었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;875&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpaKN3/btsJGAEaoXR/uXmxsFJrnFTpBEmIJy0kR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpaKN3/btsJGAEaoXR/uXmxsFJrnFTpBEmIJy0kR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpaKN3/btsJGAEaoXR/uXmxsFJrnFTpBEmIJy0kR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpaKN3%2FbtsJGAEaoXR%2FuXmxsFJrnFTpBEmIJy0kR0%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;662&quot; height=&quot;453&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;875&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;b&gt;개선점:&amp;nbsp;&lt;/b&gt;앵귤러와 달리 데이터가 부모에서 자식으로 흐르는 단방향 데이터 흐름을 채택하여 데이터의 흐름이 명확하고 예측 가능해졌고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태와 생명주기를 관리할 수 있는 hooks 방식을 채택해 코드의 간결함과 재사용성을 높임, JSX을 사용하여 UI를 선언적으로 작성할 수 있게 됨&lt;/p&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;CSR로 인한 SEO 저하 ,리렌더링 성능 문제(props 가 변경되면 컴포넌트도 리렌더링), 타 SPA 프레임워크 대비 right-way 기준이 모호함&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;상태 관리의 진화 Flux 패턴, Redux, Zustand... 의 등장&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 애플리케이션이 복잡해짐에 따라 컴포넌트 간의 상태 공유와 관리가 어려워졌습니다. 데이터의 흐름을 명확히 하고, 예측 가능한 방식으로 상태를 관리할 필요성이 대두되었습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Flux 패턴&lt;/h3&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;b&gt;주요 특징&lt;/b&gt;: 단방향 데이터 흐름. 상태가 변할 때마다 액션을 통해 Dispatcher가 상태를 업데이트하도록 하여 데이터 흐름을 명확히 함.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결하는 문제&lt;/b&gt;: 복잡한 상태 관리 및 컴포넌트 간의 비동기적 데이터 처리 문제.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;393&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/egv05W/btsJGwhHEXG/MkbWHFllFqyFs2K0IxK770/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/egv05W/btsJGwhHEXG/MkbWHFllFqyFs2K0IxK770/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/egv05W/btsJGwhHEXG/MkbWHFllFqyFs2K0IxK770/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fegv05W%2FbtsJGwhHEXG%2FMkbWHFllFqyFs2K0IxK770%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;1300&quot; height=&quot;393&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;393&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;text-align: left;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;Redux&lt;/h3&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;: Flux의 복잡성을 단순화하고, 상태 관리를 더 직관적으로 만들기 위해 탄생.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주요 특징&lt;/b&gt;: 단일 스토어, 불변성, 미들웨어 지원. 상태를 관리하기 위해 순수 함수인 리듀서를 사용.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;해결하는 문제&lt;/b&gt;: 대규모 애플리케이션에서 상태를 더 쉽게 관리하고 디버깅할 수 있도록 지원. 개발자 도구와의 통합으로 상태 변화를 쉽게 추적 가능. props drilling문제 해결&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재는 zustand, recoil, jotai 등의 전역상태관리 도구들이 생겼다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;541&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oIte2/btsJGXsmI8A/GaTysrbksRUQmo6zpx3ax1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oIte2/btsJGXsmI8A/GaTysrbksRUQmo6zpx3ax1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oIte2/btsJGXsmI8A/GaTysrbksRUQmo6zpx3ax1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoIte2%2FbtsJGXsmI8A%2FGaTysrbksRUQmo6zpx3ax1%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;1350&quot; height=&quot;541&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;541&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;b&gt;주의해야할 점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 전역 상태를 사용할 때 메모리 사용량 증가, 상태의 비효율적인 관리, GC 등의 문제를 고려해야 하는 번거로움도 생겼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Next.js: 서버사이드 렌더링과 정적 사이트 생성&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;SEO와 초기 로딩 성능 문제 해결:&lt;/b&gt; Next.js는 React 기반의 프레임워크로, 서버사이드 렌더링(SSR)과 정적 사이트 생성(SSG)을 지원하여 검색 엔진 최적화(SEO)와 첫 화면 로딩 성능 문제를 해결했습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;하이브리드 애플리케이션:&lt;/b&gt; Next.js는 클라이언트사이드 렌더링(CSR)의 문제를 보완하면서도, SSR과 SSG를 유연하게 사용할 수 있는 하이브리드 애플리케이션을 가능하게 했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;571&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PlpyO/btsJHCHOpQS/9CUC2DMRDgKjFKLkzst5K1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PlpyO/btsJHCHOpQS/9CUC2DMRDgKjFKLkzst5K1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PlpyO/btsJHCHOpQS/9CUC2DMRDgKjFKLkzst5K1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPlpyO%2FbtsJHCHOpQS%2F9CUC2DMRDgKjFKLkzst5K1%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;790&quot; height=&quot;451&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;571&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;이외에도 Nextjs에서 여러 기술을 도입해 성능을 개선하고 있다.&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;Incremental Static Regeneration (ISR)&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; ISR은 SSG의 확장으로, 정적 페이지를 생성하되, 특정 시간 간격으로 페이지를 재생성하여 최신 콘텐츠를 제공하는 기능입니다. 이는 정적 사이트의 장점과 동적 사이트의 유연성을 결합한 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사용 예:&lt;/b&gt; 뉴스 사이트나 블로그에서 최신 기사를 주기적으로 업데이트할 때 유용합니다. 예를 들어, 10분마다 새로 고침 하여 콘텐츠를 최신 상태로 유지할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZ8iT2/btsJIqmmXBq/4FMkfWG7mkVgMhgWSpD8Yk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZ8iT2/btsJIqmmXBq/4FMkfWG7mkVgMhgWSpD8Yk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZ8iT2/btsJIqmmXBq/4FMkfWG7mkVgMhgWSpD8Yk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZ8iT2%2FbtsJIqmmXBq%2F4FMkfWG7mkVgMhgWSpD8Yk%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;629&quot; height=&quot;354&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&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;size18&quot;&gt;서버 컴포넌트&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;개념:&lt;/b&gt; Next.js 13에서 도입된 서버 컴포넌트는 서버에서 직접 렌더링 되며, 클라이언트에게 전달되는 HTML을 최소화하여 성능을 향상하는 기능입니다. 서버에서 데이터를 가져오고, 해당 데이터를 기반으로 UI를 구성합니다.&lt;br /&gt;&lt;br /&gt;&lt;u&gt;쉽게 말해,  서버 컴포넌트(Server Components)는 서버사이드 렌더링(SSR)을 컴포넌트 단위로 세분화한 방식으로 볼 수 있습니다&lt;/u&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;장점:&lt;/b&gt; 클라이언트의 자원 사용을 줄이고, 서버에서 모든 비즈니스 로직을 처리할 수 있어 애플리케이션의 성능을 최적화합니다. 데이터 패칭과 UI 렌더링이 서버에서 이루어지기 때문에, 클라이언트 측의 부담이 크게 줄어듭니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Vue.js: Right-way가 명확한&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1960&quot; data-origin-height=&quot;960&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mhf6L/btsJIgqK0JF/xEDkrIRklEec8LcgbO9V4k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mhf6L/btsJIgqK0JF/xEDkrIRklEec8LcgbO9V4k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mhf6L/btsJIgqK0JF/xEDkrIRklEec8LcgbO9V4k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmhf6L%2FbtsJIgqK0JF%2FxEDkrIRklEec8LcgbO9V4k%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;780&quot; height=&quot;382&quot; data-origin-width=&quot;1960&quot; data-origin-height=&quot;960&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;b&gt;명확한 right-way: &lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;코드의 양이 많아지면 &quot;코드짜는 법이 제한적&quot;인건&lt;span&gt; 큰 장점이 될 수 있고 vue는 react에 비해 코드 짜는 답이 정해져있습니다.&amp;nbsp;&lt;br /&gt;&lt;br /&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: #000000; text-align: start;&quot;&gt;&lt;span&gt;ex) &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;map, forEach, for in, for of &amp;gt; &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;HTML안에 v-for&lt;span&gt;&amp;nbsp;사용&lt;/span&gt;&lt;/span&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 data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쉬운 학습 곡선&lt;/b&gt;: Vue는 직관적인 API와 HTML 템플릿 구문을 제공하여 초보자가 쉽게 배우고 사용할 수 있습니다.&lt;br /&gt;HTML, CSS, JS만 알고 있어도 비교적 배우기 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;명확한 컴포넌트 구조&lt;/b&gt;: Single File Component(SFC) 형식을 통해 HTML, CSS, JavaScript를 한 파일에서 관리할 수 있어 코드 관리가 용이합니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;Svelte: 컴파일 타임에서의 최적화&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;648&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/w6S2Q/btsJHUBuTJ4/RiKGVklMtg124rYyPWLma0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/w6S2Q/btsJHUBuTJ4/RiKGVklMtg124rYyPWLma0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/w6S2Q/btsJHUBuTJ4/RiKGVklMtg124rYyPWLma0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fw6S2Q%2FbtsJHUBuTJ4%2FRiKGVklMtg124rYyPWLma0%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;691&quot; height=&quot;373&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;648&quot;/&gt;&lt;/span&gt;&lt;/figure&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;Virtual DOM 없이 빠른 성능:&lt;/b&gt; Svelte는 Virtual DOM을 사용하지 않고 컴파일 타임에 UI 컴포넌트를 최적화하여 더욱 빠른 성능을 제공합니다. (런타임 라이브러리의 필요성이 줄어듦)&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;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현대 프론트엔드는 빠르게 변화하고 있으며, 다양한 프레임워크와 기술이 등장하고 있습니다. &lt;br /&gt;개인적으로 느끼는 바는 SSR(서버사이드 렌더링)과 SPA(싱글 페이지 애플리케이션) 사이에서 회귀하는 경향이 있다는 점입니다. 초기의 SSR은 SEO와 초기 로딩 성능에서 큰 장점을 제공했지만, SPA의 사용자 경험과 인터랙티브한 요소가 점차 중요해지면서 두 방식 간의 균형을 찾고 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Next.js와 같은 프레임워크는 이러한 변화의 좋은 예시입니다. Next.js는 SSR과 SSG(정적 사이트 생성)를 모두 지원하여 개발자가 필요에 따라 최적의 방식을 선택할 수 있도록 해줍니다. 또한, 풀스택 개발을 지원함으로써 프론트엔드와 백엔드의 경계를 허물고, 보다 통합된 개발 환경을 제공합니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vue, Svelte 등은 React의 단점을 개선하는 방향으로 발전하고 있지만, React의 압도적인 점유율과 넓은 생태계는 쉽게 흔들리지 않을 것으로 보이네요&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignRight&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1377&quot; data-origin-height=&quot;563&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OKfCO/btsJInwoLk0/Q0tkJz4Kht7ViMWJgWSZs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OKfCO/btsJInwoLk0/Q0tkJz4Kht7ViMWJgWSZs1/img.png&quot; data-alt=&quot;하지만 jQuery는 여전히 리액트 다음으로 인기가 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OKfCO/btsJInwoLk0/Q0tkJz4Kht7ViMWJgWSZs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOKfCO%2FbtsJInwoLk0%2FQ0tkJz4Kht7ViMWJgWSZs1%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;748&quot; height=&quot;563&quot; data-origin-width=&quot;1377&quot; data-origin-height=&quot;563&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;하지만 jQuery는 여전히 리액트 다음으로 인기가 있다.&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;&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;그리고 최근엔 AI 툴의 등장으로 HTML, CSS, 심지어 JavaScript 코드 작성의 생산성을 크게 향상시켰습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;800&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bS2P4d/btsJHZisnWm/3fRaKC75f5vLfo7q2cPCB0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bS2P4d/btsJHZisnWm/3fRaKC75f5vLfo7q2cPCB0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bS2P4d/btsJHZisnWm/3fRaKC75f5vLfo7q2cPCB0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbS2P4d%2FbtsJHZisnWm%2F3fRaKC75f5vLfo7q2cPCB0%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;567&quot; height=&quot;354&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;800&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;또한, 사용자 경험(UX) 디자인에 대한 이해와 설계 능력도 필수적입니다. &lt;br /&gt;&lt;br /&gt;AI 도구가 기본적인 UI 요소를 생성하더라도, 사용자와의 상호작용을 최적화하고 감동을 줄 수 있는 디자인은 여전히 개발자의 몫입니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로, 커뮤니케이션 능력 역시 중요해질 것입니다. 팀 내 협업이나 고객 요구 사항을 효과적으로 이해하고 전달하는 능력이 프로젝트의 성공에 큰 영향을 미칠 수 있습니다. AI가 도와주는 작업 속에서도 사람 간의 소통과 협력이 필요한 부분이 여전히 존재하기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 AI 시대에 발맞춰 프론트엔드 개발자는 기술적 능력뿐만 아니라 다양한 소프트 스킬도 함께 발전시켜 나가야 할 것 같습니다.&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;&amp;nbsp;&lt;/h3&gt;</description>
      <category>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/233</guid>
      <comments>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%9D%98-%EC%97%AD%EC%82%AC#entry233comment</comments>
      <pubDate>Sun, 22 Sep 2024 13:41:42 +0900</pubDate>
    </item>
    <item>
      <title>자바스크립트가 프로토타입을 선택한 이유</title>
      <link>https://hmk1022.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EA%B0%80-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85%EC%9D%84-%EC%84%A0%ED%83%9D%ED%95%9C-%EC%9D%B4%EC%9C%A0</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;p data-ke-size=&quot;size16&quot;&gt;여러 글들에선 &quot;프로토타입은 자바스크립트에서 상속을 지원하기 위한 방법&quot;라고 이야기하곤 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기엔 꼬리에 꼬리를 무는 질문이 이어질 수 있는데, &quot;왜 다른 언어처럼 클래스가 아니라 프로토타입을 사용하는가?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;프로토타입과 클래스의 차이는 뭘까?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외에도 자바스크립트엔 면접 단골 질문으로도 유명한 this, 호이스팅, 클로저, 스코프체인 등등.. 이 있다.&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-origin-width=&quot;1280&quot; data-origin-height=&quot;853&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddfRcQ/btsJGuxjaUI/Wmq7RqcUsgKsvsPOrDcyXk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddfRcQ/btsJGuxjaUI/Wmq7RqcUsgKsvsPOrDcyXk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddfRcQ/btsJGuxjaUI/Wmq7RqcUsgKsvsPOrDcyXk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FddfRcQ%2FbtsJGuxjaUI%2FWmq7RqcUsgKsvsPOrDcyXk%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;1280&quot; height=&quot;853&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;853&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;&quot;호이스팅은 자바스크립트에서 코드 실행 시 전체 코드를 선언부 상단으로 올려 실행가능한 상태인지 확인한다&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;this는 기본적으로 global을 가리키고 실행 콘텍스트에 따라 달라질 수 있으며 call, bind, apply 등을 통해 제어할 수 있다.&quot;&lt;/p&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;FE 개발자로서 위의 질문과 답변은 정형화되어 있다고 생각했다.&lt;/p&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;b&gt;근본적인 &quot;왜?&quot;에 대한 질문을 타개하고자 자바스크립트의 프토로토타입 선택이유에 대해 정리&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;a href=&quot;https://citeseerx.ist.psu.edu/document?repid=rep1&amp;amp;type=pdf&amp;amp;doi=30fcb7807ce73f16222761b97e36154f12349efb&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Classses vs Prototypes Some Pliosophical and Historical Observations&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 논문을 토대로 이야기하자면 prototype과 class의 OOP는 완전히 상반되는 방식이라고 볼 수 있다.&lt;/p&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;특히 문맥(context)을 매우 강조하는 철학적 근거에서 태어난 녀석이라 렉시컬 스코프에 의한 호이스팅과 실행 문맨에 의해 결정되는 this가 필연적으로 발생할 수밖에 없다.&lt;/p&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;i&gt;자바스크립트의 프로토타입 선택 이유에 대해 다뤄보면서 실행 context, this, 호이스팅, 클로저 등이 발생하는&amp;nbsp;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;이유에 대해 정형화된 암기를 벗어나 근본적인 이유에 대해서 이해할 수 있기를 바랍니다.&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&quot;서양 철학은 플라톤의 각주에 불과하다 - 화이트 헤드&quot;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로토타입을 이해하려면 그 대척점에 있는 클래스의 기원을 알아햐 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스 기반 객체지향 언어(Java, C#)를 다뤄봤다면 이미 알고 있는 내용일 수도 있습니다.&lt;/p&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;의자&lt;/b&gt;를 예시로 보면 우리가 앉아있는 &lt;b&gt;의자는 여러 가지 형태가 존재&lt;/b&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사무용 의자, 공원 벤치, 원목 의자 등등 이러한 &lt;b&gt;수많은 의자가 실제로 존재한다면 반드시&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그 본질적이고 추상적인 &quot;의자&quot;라는 것이 존재&lt;/b&gt;한다는 것이지요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 본질 세계를 이데아(Idea)라고 합니다. &lt;b&gt;현실의 의자는 모두 이데아의 &quot;의자&quot;를 모방한 의자&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;영어의 &quot;관사&quot;를 보면 이러한 방식이 두드러지는데요,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영어에서 이데아의 세계에 있는 의자를 이야기할 때 그냥 &quot;chair&quot;라고 얘기하는 것이 그 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 현실에 존재하는 의자를 가리킬 땐 어떻게 이야기할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현실에 존재하는 것을 얘기할 땐 단어 그대로 이야기하지 않고 &quot;때&quot;를 묻혀서 이야기합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 &quot;the chair&quot;라고 얘기해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- chair : 이데아에 존재하는 본질적인, 추상적인 의자. 현실세계에 존재하지 않음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- this chair, a chair : 현실 세계에 존재하는 의자&lt;/p&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;바로 &quot;클래스 기반 객체지향 프로그래밍 언어&quot;입니다.&lt;/p&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;Java를 예시로 볼까요?&lt;/p&gt;
&lt;pre id=&quot;code_1726877321246&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Chair {  // class 선언 자체는 이데아에 존재하는 의자
... 
}

Chair myChair = new Chair(); // new 키워드로 추상적으로만 존재하던 의자를 메모리라는 현실세계로&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;위 코드에서 레퍼런스 타입이라 불리는 Chair 클래스는 이데아에 존재하는 추상적인 개념&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 코드상으로만 존재하지 실제 메모리상에는 존재하지 않습니다. (사실, PermGen 영역에 있겠지만 Heap 메모리를 실제 하는 공간으로 보겠습니다.)&lt;/p&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;바로 new 키워드 사용하면 됩니다. new Chair();를 하는 순간 추상적으로만 존재하던 의자가 메모리라는 현실시계에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구체적으로 존재(인스턴스화)하게 됩니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style6&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;분류(Classification)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 플라톤의 이데아 이론은 그의 제자 아리스토텔레스에 의해서 &quot;분류(Classification)&quot;란 개념으로 정리됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;class라는 키워드는 &quot;학급&quot;을 의미하는 게 아니라 Classification에서 나온 키워드입니다.&lt;/p&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;&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;돌고래의 속성에 따른 분류&lt;/p&gt;
&lt;pre id=&quot;code_1726878581429&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 포유류(Mammal) 추상 클래스: 모든 포유류는 허파로 숨을 쉬고 새끼를 낳음
abstract class Mammal {
    abstract void breathe();    // 숨쉬기 메서드 (허파로 호흡)
    abstract void giveBirth();  // 새끼를 낳는 메서드
}

// 돌고래(Dolphin) 클래스: 포유류의 특징을 상속받아 구현
class Dolphin extends Mammal {

    @Override
    void breathe() {
        System.out.println(&quot;돌고래는 아가미가 아닌 허파로 숨을 쉽니다.&quot;);
    }

    @Override
    void giveBirth() {
        System.out.println(&quot;돌고래는 새끼를 낳고 젖을 먹입니다.&quot;);
    }
}

// 어류(Fish) 추상 클래스: 어류는 아가미로 호흡하고 알을 낳음
abstract class Fish {
    abstract void breathe();
    abstract void layEggs();
}

// 상어(Shark) 클래스: 어류의 특징을 상속받아 구현
class Shark extends Fish {

    @Override
    void breathe() {
        System.out.println(&quot;상어는 아가미로 숨을 쉽니다.&quot;);
    }

    @Override
    void layEggs() {
        System.out.println(&quot;상어는 알을 낳습니다.&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;프로토타입(Prototype)&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&quot;서양 철학은 플라톤의 각주에 불과하다 - 화이트 헤드&quot; 하지만 이 말에는 &quot;비트겐슈타인 이전까지&quot;라는 단서를 붙여야 한다.&lt;/i&gt;&lt;i&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;- 와스피 히잡&lt;/i&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이제야 프로토타입 이야기가 나오는데요, 프로토타입을 이야기하기 위해서 분류(Classification)에 대해 반드시 알아야 할 필요가 있기&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;때문에 짚고 넘어갔습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;프로토 타입은 분류의 개념을 정면으로 반박하여 나온 이론이기 때문입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;19세기 철학자 비트겐슈타인은 아리스토텔레스의 분류 개념을 정면으로 반박합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;i&gt;&quot;공유 속성의 관점에서 정의하기 어려운 개념이 있다(사실) 올바른 분류란 없다 - 비트겐슈타인&quot;&lt;br /&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이것을 뒷받침하기 위해 들고 온 것은 바로 게임입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;게임은 일반적으로 &quot;승리&quot;와 &quot;패배&quot;가 명확합니다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;하지만 비트겐슈타인은 이에 대한 반론으로 &quot;승리&quot;와 &quot;패배&quot;가 없는 ring around a rosy라는 게임을 가져옵니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cDeVcQ/btsJIlFmI8w/O3SdPyetwWWPAsFpOVDiA0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cDeVcQ/btsJIlFmI8w/O3SdPyetwWWPAsFpOVDiA0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cDeVcQ/btsJIlFmI8w/O3SdPyetwWWPAsFpOVDiA0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcDeVcQ%2FbtsJIlFmI8w%2FO3SdPyetwWWPAsFpOVDiA0%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;602&quot; height=&quot;339&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그냥 빙글빙글 돌다 다 같이 주저 않는 게임으로 누구도 승리, 패배하지 않죠(재미없을 것 같긴 하네요)&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여하튼 이 게임엔 공유 속성(property)이 없네요&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 승리 / 패배? 없음&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 숙련도 여부? 행운(주사위) 위주 게임은 없잖아&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 플레이어 존재여부? 플레이어가 전혀 필요하지 않은 게임도 있잖아&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;특히 예술작품의 경우 공통 속성을 정의하기 더 어렵습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;즉, 좀 더 철학적으로 본다면 &quot;게임&quot;, &quot;예술&quot; 등의 단어는 결코 속성으로 규정할 수 없습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;i&gt;&lt;br /&gt;&quot;세계에 미리 내재되어서 대상과 언어를 완전히 규정하는 어떤 언어란 존재하지 않는다. - 비트겐슈타인&quot;&lt;/i&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Java와 같은 객체 지향 프로그래밍 언어로 개발하다 보면 한계에 부딪힐 때가 있는데요,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;최적의 클래스를 설계를 만드는 것이 어려울 때가 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;속성(property)으로 분류하는 것은 확정성을 고려하면 좋은 방식이 아니었습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;정답이라고 생각했던 설계도 개발이 진행되면서 뒤엎는 경우가 많았습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;멋들어진 상속관계는 기술부채가 되어버리는 경우도 많았죠,&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;물론 도메인 기반 설계, SOLID, 디자인 패턴을 더 습득하며 그럴싸한 클래스를 설계할 수 있도록 갈고닦아야겠지요&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;한 번에 완벽한 디자인이 나오는 것은 너무나 어렵습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 분류(Classification)에 대해 강하게 비판한 비트겐슈타인, 그렇다면 그의 대안은 무엇이었을까요?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;i&gt;&quot;표현은 삶의 흐름 속에서만 의미를 갖는다 - 비트겐슈타인&quot;&lt;/i&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&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;의미사용이론(the use theory of meaing)&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;비트겐슈타인 일생의 후기에 내놓은 이론입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;사용(use)에 의해 의미(meaning)가 결정된다는 이론입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;단어의 쓰임새가 곧 의미가 됩니다. 즉,&lt;b&gt; 단어의 진정한 본래의 의미란 존재하지 않고 상황과 맥락에 의해서 결정된다&lt;/b&gt;라고&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;주장하고 있습니다. 그러니 단어의 의미를 백날 분석해 봤자 소용이 없다는 것입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;비트겐슈타인은 &quot;벽돌&quot;을 예로 들었습니다. 누군가 벽돌!이라 외쳤을 때 상황마다 그 의미는 달라집니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 벽돌이 필요할 때 : 벽돌을 달라&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 벽돌로 보수해야 할 때 : 벽돌을 채우라&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 벽돌이 떨어질 때: 벽돌을 피해라&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위의 내용이 와닿지 않는다면 &lt;b&gt;맥락(context)이 중요하다는 것만 기억하시면 됩니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;콘텍스트로 프로토타입 기반 언어의 실행 콘텍스트를 설명할 수 있습니다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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; 가족 유사성(Family Resemblance)&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;478&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nATiJ/btsJHXShyuJ/7hmEcil7DhDidOkOKKuUvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nATiJ/btsJHXShyuJ/7hmEcil7DhDidOkOKKuUvk/img.png&quot; data-alt=&quot;출처 :&amp;amp;nbsp; https://www.slideshare.net/vcmlab/cog5-lecppt-chapter08&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nATiJ/btsJHXShyuJ/7hmEcil7DhDidOkOKKuUvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnATiJ%2FbtsJHXShyuJ%2F7hmEcil7DhDidOkOKKuUvk%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;637&quot; height=&quot;478&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;478&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 :&amp;nbsp; https://www.slideshare.net/vcmlab/cog5-lecppt-chapter08&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;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;그런데도 우리는 이 그림을 보고 전형적인 특징을 통해 &quot;가족&quot;으로 분류합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 분류 방식을 &quot;가족 유사성&quot;에 의한 분류라고 합니다.&lt;/p&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;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;Rosch의 프로토타입 이론&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이론의 마지막 장입니다. 드디어 &quot;프로토타입&quot;이라는 단어를 직접 다루는 이론입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비트겐슈타인의 의미사용이론, 가족유사성은 1970년경 철학자 Eleanor Rosch에 의해&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로토타입 이론(Prototype theory)으로 정리됩니다.&lt;/p&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;- 코코넛: 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;점수가 높을수록 &quot;가족 유사성&quot;이 높다고 볼 수 있습니다.&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;이 실험을 통해 로쉬는 &quot;인간은 등급이 매겨진 구조를 가진다&quot;라고 주장합니다.&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;이렇게 분류를 하다 보면 가장 높은 등급을 가진 녀석이 나올 텐데요, 이것이 바로 Prototype&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;&quot;새&quot;를 예로 들어보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;참새&quot;는 새의 범주는 대표할 만한 가장 전형적인 새입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것을 &quot;원형(prototype)&quot;으로 간주해 봅시다.&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;700&quot; data-origin-height=&quot;645&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NqkeR/btsJItpBVwf/BN89yOwE3efy0YSV9Uksnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NqkeR/btsJItpBVwf/BN89yOwE3efy0YSV9Uksnk/img.png&quot; data-alt=&quot;출처 :&amp;amp;nbsp; https://laurabecker.gitlab.io/classes/as/08-semantics.pdf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NqkeR/btsJItpBVwf/BN89yOwE3efy0YSV9Uksnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNqkeR%2FbtsJItpBVwf%2FBN89yOwE3efy0YSV9Uksnk%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;700&quot; height=&quot;645&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;645&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 :&amp;nbsp; https://laurabecker.gitlab.io/classes/as/08-semantics.pdf&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;같은 새지만 &quot;타조&quot;는 분류에선 원형과 가장 멀리 떨어진 &quot;비전형적인&quot; 새가 됩니다.&lt;/p&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;즉, 객체는 &quot;정의&quot;로부터 분류되는 것이 아니라 가장 보기 좋은(prototype exemplar)로부터 범주화됩니다.&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;만약 우리가 새로운 대상을 접해서 분류해야 한다면, 우리는 새로운 대상의 몇 가지 특징만 원형(prototype)과&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;바로 같은 단어라 할지라도 누가 어떤 상황(context)에서 접했느냐에 따라 의미가 달라질 수 있습니다 - 의미사용론&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들면 아이가 생각하는 새의 범주엔 &quot;참새&quot;는 속하지만 &quot;펭귄&quot;은 해당범주에 속할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이가 생각할 때 펭귄은 매우 비전형적이기 때문이죠&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 조류학자가 생각할 때 &quot;참새&quot;와 &quot;펭귄&quot;은 명확하게 유사한 새의 범주에 속할 수 있습니다.&lt;/p&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;size16&quot;&gt;- 현실에서 존재는 것 중 가장 좋은 본보기를 원형(prototype)으로 선택&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 문맥(context)에 따라 의미가 달라진다.&lt;/p&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;프로토타입 기반 객체지향 프로그래밍&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;프로토타입 기반 OOP 언어의 특징은 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 개별 객체(instance) 수준에서 메서드와 변수를 추가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 객체 생성은 일반적으로 복사를 통해 이루어짐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 확장(extends)은 클래스가 아니라 위임(delegation)을 통해 이뤄짐&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;- 설계는 맥락(context)에 의해 평가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;javascript 언어를 사용하는 사람의 관점으로 중요하다 생각되는 부분을 되짚어보면&lt;/p&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;- 프로토타입 언어에서는 &quot;분류&quot;를 우선하지 않는다. 생성된 객체 위주로 유사성을 정의한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- 쓰임새는 contenxt에 의해 평가된다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp;&lt;/b&gt;&amp;gt; 실행 콘텍스트, 스코프 체인이 파생됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;gt; 클로저, this, 호이스팅 등등 이 모든 것들이 프로토타입의 &quot;맥락&quot;을 표현하기 위함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;자바스크립트의 프로토타입&lt;/h3&gt;
&lt;pre id=&quot;code_1726883363788&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function 참새(){
    this.날개갯수 = 2;
    this.날수있나 = true;
}
const 참새1 = new 참새();

console.log(&quot;참새의 날개 갯수 : &quot;, 참새1.날개갯수); // 2

function 닭(){
  this.벼슬 = true;
}
닭.prototype = 참새1; // reference(오른쪽이 인스턴스인 점 주목)
const 닭1 = new 닭();
console.log(&quot;닭1 날개 : &quot;, 닭1.날개갯수, &quot;, 날수있나? &quot;, 닭1.날수있나); // 2, true
닭1.날수있나 = false;
console.log(&quot;다시 물어본다. 닭1은 날 수 있나? :&quot;, 닭1.날수있나); // false
// 아래는 고전적인 방식의 프로토타입 연결
function 펭귄(){
    참새.call(this);    // copy properties
}
펭귄.prototype = Object.create(참새.prototype); // 프로토타입 연결
const 펭귄1 = new 펭귄();
console.log(&quot;펭귄1 날개 : &quot;, 펭귄1.날개갯수, &quot;, 날수있나? &quot;, 펭귄1.날수있나); // 2, true
펭귄1.날수있나 = false;
console.log(&quot;다시 물어본다. 펭귄1은 날 수 있나? :&quot;, 펭귄1.날수있나); // false&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;9ab5&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;5L : 날개가 2개, 날 수 있는 참새 1 이 있습니다.&lt;/li&gt;
&lt;li id=&quot;68b4&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;13L : 참새 1을 프로토타입으로 갖는 닭 1 이 생겼습니다. 여기서 주목할 점은 오른쪽이 참새(함수)가 아니라 참새 1(인스턴스)인 점입니다. 프로토타입 이론은 이미 존재하는 사물을 통해 범주화한다는 점에서 일치합니다&lt;/li&gt;
&lt;li id=&quot;8622&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;14L : 닭의 정의(10L)에는 날개개수가 없지만 2가 출력됩니다. 프로토타입 체인에 의해 참새 1의 속성에 접근했기 때문입니다.&lt;/li&gt;
&lt;li id=&quot;8c71&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;15L : 닭 1 은 날 수 없다고 합니다. 닭 1은 날 수 없어도 프로토타입에 해당하는 참새 1 은 날 수 있습니다. (닭 1은 참새 1 프로토타입에서 좀 더 멀어졌습니다) 같은 속성을 변경해도 프로토타입 객체의 속성은 변경되지 않은 점에 주의&lt;/li&gt;
&lt;li id=&quot;464d&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;17L~25L : 고전적인 방식으로 프로토타입을 사용해 봤습니다. 프로토타입에선 객체 생성을 통해 확장한다는 부분이 좀 더 직관적으로 다가옵니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p id=&quot;39db&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;위 코드는 아래처럼 도식화할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&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-origin-width=&quot;700&quot; data-origin-height=&quot;616&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FWhhI/btsJGnZbpKC/5IJwK4pIU4GikOAoidFBG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FWhhI/btsJGnZbpKC/5IJwK4pIU4GikOAoidFBG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FWhhI/btsJGnZbpKC/5IJwK4pIU4GikOAoidFBG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFWhhI%2FbtsJGnZbpKC%2F5IJwK4pIU4GikOAoidFBG0%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;700&quot; height=&quot;616&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;616&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;cb22&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;닭 1의 원형(프로토타입)은 참새 1이다&lt;/li&gt;
&lt;li id=&quot;7fe9&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;닭 1에 없는 속성(날개개수)은 프로토타입 체인을 통해 참조된다&lt;/li&gt;
&lt;li id=&quot;838c&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;닭 1에 동일한 속성명(날 수 있나)을 추가해도 원형은 변하지 않는다(위임)&lt;br /&gt;&amp;gt; 원리적으로는 닭 1을 통해 원형(prototype)을 변경하는 건 불가능해야 한다. 하지만 JS 에선 문법적으로 가능. (권장하지 않음)&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;자바스크립트의 어휘적 범위(lexical scope)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의미사용론에 따르면 단어의 의미는 그 어휘적인, 근처 환경에서의 의미가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이는 javascritp에서 다음처럼 적용됩니다.&lt;/p&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;변수의 의미는 그 어휘적인(Lexical), 실행 문맥(Excution Context)에서의 의미가 된다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 실행문맥(context)의 모든 선언을 참고(호이스팅)해 의미를 정의합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;호이스팅은 자바스크립트의 대표적인 특징으로 면접단골 질문이기도 하죠&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;대부분 &quot;코드가 로드될 때 선언부가 상단으로 끌어올려지는&quot; 정도로 대답을 합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;틀린 대답은 아니지만 아쉽습니다. 좀 더 보태면&amp;nbsp; 아래처럼 대답할 수 있겠네요&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot;&gt;&amp;lsquo;실행 콘텍스트 생성 시 렉시컬 스코프 내의 선언이 끌어올려지는 게 호이스팅이다'&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;span style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot;&gt;&quot;프로토타입 기반 언어인 자바스크립트에서는 &amp;lsquo;단어의 의미가 사용되는 근처 환경&amp;rsquo;에서의 &amp;lsquo;근처'를 어휘적인 범위(Lexical Scope)로 정의했습니다. 자바스크립트 엔진은 코드가 로드될 때 실행 콘텍스트를 생성하고 그 안에 선언된 변수, 함수를 실행 콘텍스트 최상단으로 호이스팅 합니다. 이러한 범위를 렉시컬 스코프라 합니다.&quot;&lt;/span&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1726884069831&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 전역 실행문맥 생성. 전체 정의(name, init) 호이스팅
var name = 'Kai';
init(); // init 실행문맥 생성. 내부 정의(name, displayName) 호이스팅
function init() {
    var name = &quot;Steve&quot;;
    function displayName() {  
      console.log(name); // 현재 실행문맥 내에 정의된게 없으니 outer 로 chain
      // var name = 'troll?'; // 주석 해제되면 호이스팅
    }
    displayName(); // displayName 실행문맥 생성. 내부 정의 호이스팅.
}&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;- 2L: 코드가 로드될 때 전역 실행문맥(Execution Scope)이 생성됩니다. 전역의 선언부를 모두 호이스팅 하게 되는데 여기선 2L의 name과 4L의 init이 렉시컬 스코프에 들어갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 3L: 렉시컬 스코프 상에 4L에 init 함수가 존재하니 에러 없이 실행할 수 있습니다. 코드 로딩 시점에 init 함수를 타고 들어가 실행 문맥을 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 4L: init 함수에 대한 렉시컬 스코프를 생성 name과 displayName이 들어옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 6L-9L: displayName 실행 문맥 내에 name이라 선언된 것이 없음. 이렇 때 Scope Change을 통해 상위 콘텍스트로 위임&lt;br /&gt;&lt;br /&gt;코드를 로드하게 되면 아래와 같은 구조가 생성됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1726884291958&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;- Global Execution // 1
   - Lexical : name, init 
- Execution : init // 2
   - Lexical : name, displayName
   - Outer : global 
- Execution : displayName // 3
   - Lexical : null
   - Outer : init&lt;/code&gt;&lt;/pre&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;700&quot; data-origin-height=&quot;484&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JLgcu/btsJHyeomZk/Koo7BKV1uMRzKwZzNPPjMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JLgcu/btsJHyeomZk/Koo7BKV1uMRzKwZzNPPjMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JLgcu/btsJHyeomZk/Koo7BKV1uMRzKwZzNPPjMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJLgcu%2FbtsJHyeomZk%2FKoo7BKV1uMRzKwZzNPPjMK%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;700&quot; height=&quot;484&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;484&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;도대체 왜 &quot;실행 문맥&quot;, &quot;렉시컬 스코프&quot;, &quot;호이스팅&quot;이 존재하는가입니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;왜?&quot;를 이해한다면 이러한 것들은 더 이상 암기과목이 아닙니다.&lt;/p&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;&quot;어휘&quot;이고 이것은 &quot;문맥&quot; 내에서만 의미를 가진다는 것이 핵심입니다.&lt;/p&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;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;자바스크립트의  this&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트의 또 다른 특징은 this이죠,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스 기반객체지향 언어에서의 this와는 완전히 다른 동작을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 문서에선 Case by case로 this가 가리키는 객체를 설명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식의 접근보단 프로토타입 관점에서 이해하고 왜 javascript에서 this가 요 모양인지 이해한다면&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; this에 대한 대표적인 오해들&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- this는 기본적으로 window다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 이벤트 리스너에 등록한 콜백의 this는 내부 bind 등을 통해 바뀌기 때문에 무엇인지 알 수 없다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- this는 외워야 한다.&lt;/p&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;&quot;대상&quot;에 따라서 같은 단어도 의미가 달라진다는 얘기입니다.&lt;/p&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;미리 분류하고 정의한 클래스를 중요하게 여기는 방식 vs 주체와 문맥을 중요하게 여기는 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래밍으로 보자면 실행(invoke)하는 &quot;객체&quot;가 중요하다는 의미입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것이 프로토타입 기반의 언어인 자바스크립트에서 this가 클래스 기반 언어들과 다르게 동작하는 이유입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;javascript에선 this가 정의된 함수가 어떻게 발화(invoke) 되었는지에 따라 가리키는 값이 달라집니다.&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; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;80f1&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;메소드 : 객체의 함수&lt;/li&gt;
&lt;li id=&quot;4089&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;메시지 : 메서드를 실행하라는 메시지 전달&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바에선 클래스의 메서드를 호출하는 것을 메시지라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트를 예로보면 foo라는 객체가 있고 그 내부에 bar()이라는 함수가 있을 때 다음처럼&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;invoke 할 객체를 지정할 수 있습니다.&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; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;a075&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;foo.bar()&lt;/li&gt;
&lt;li id=&quot;c4c1&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;bar.call(foo)&lt;/li&gt;
&lt;li id=&quot;5196&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;var boundBar = bar.bind(foo)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위처럼 foo 객체를 통해 invoke 된 함수는 내부 this가 무조건 foo를 가리키게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 아무것도 지정된 게 없으면 global(브라우저는 window)을 가리키겠죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1726885820117&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var someValue = 'hello';
function outerFunc() {
    console.log(this.someValue); // 첫번째 : ?, 두번째 : ?
    this.innerFunc();
}
const obj = {
    someValue : 'world',
    outerFunc,
    innerFunc : function() {
        console.log(&quot;innerFunc's this : &quot;, this); // 첫번째 : ?, 두번째 : ?
    }
}
obj.outerFunc(); // 첫번째
outerFunc(); // 두번째&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;9116&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;3L : 13L 에서 호출한 첫 번째는 world가, 14L 에서 호출한 두 번째는 hello 가 찍힙니다. outerFunc 가 누구를 통해 발화되었는지를 알면 this 가 무엇이 될지 알 수 있습니다&lt;/li&gt;
&lt;li id=&quot;7009&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;4L : obj를 통해 발화되면 innerFunc 가 존재하기 때문에 호출되지만, 글로벌에서 발화되면 innerFunc 가 없기 때문에 에러가 납니다&lt;/li&gt;
&lt;li id=&quot;8631&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;10L : this 가 이중으로 들어가 있어 헷갈릴 수 있는데 복잡하지 않습니다. this(obj)를 통해 발화했기 때문에 첫 번째는 obj 가 됩니다.&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;13L의 obj.outerFunc 호출 상황을 그림으로 표현하면 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BmnIW/btsJIqmaplS/CsLDJ3xL3QL6SoshGt0fn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BmnIW/btsJIqmaplS/CsLDJ3xL3QL6SoshGt0fn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BmnIW/btsJIqmaplS/CsLDJ3xL3QL6SoshGt0fn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBmnIW%2FbtsJIqmaplS%2FCsLDJ3xL3QL6SoshGt0fn1%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;700&quot; height=&quot;392&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;392&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;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;d04a&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;시작 : 자바스크립트 엔진이 코드를 실행합니다. (브라우저에서 use strict 모드가 아닌 경우 this는 window를 가리킵니다)&lt;/li&gt;
&lt;li id=&quot;c3c6&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;1번 : 코드의 13L을 만나면 엔진은 obj에 outerFunc를 실행하라는 메시지를 보냅니다.&lt;/li&gt;
&lt;li id=&quot;baff&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;2번 : obj에서 outerFunc를 발화합니다. 코드 로드 시 만들어져 있는 실행문맥을 참고해 실행합니다. 이때 실행 문맥상의 this는 발화한 obj를 가리킵니다.&lt;/li&gt;
&lt;li id=&quot;388b&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;3번 : 실행 중에 this.innerFunc를 만납니다. 엔진은 this 가 가리키는 obj에 innerFunc 를 실행하라는 메시지를 보냅니다.&lt;/li&gt;
&lt;li id=&quot;925e&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;4번 : obj 에 innerFunc 이 선언되어 있으니 잘 실행합니다&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;f34b&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;14L의 outerFunc 호출 상황을 그림으로 그려보면 아래와 같습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;393&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8DefJ/btsJHp9DzKs/d6HmJwb6eg3hX1aFTHXWB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8DefJ/btsJHp9DzKs/d6HmJwb6eg3hX1aFTHXWB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8DefJ/btsJHp9DzKs/d6HmJwb6eg3hX1aFTHXWB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8DefJ%2FbtsJHp9DzKs%2Fd6HmJwb6eg3hX1aFTHXWB0%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;700&quot; height=&quot;393&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;393&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;7e85&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;1번 : 코드의 14L을 만나면 엔진은 자신(global)의 실행문맥상에 존재하는 outerFunc을 호출합니다.&lt;/li&gt;
&lt;li id=&quot;d498&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;2번 : 발화한 지점이 엔진(global)이니 this는 엔진을 가리킵니다. 엔진에 innerFunc을 실행하라는 메시지를 보냅니다&lt;/li&gt;
&lt;li id=&quot;81ad&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;3번 : 글로벌 실행문맥에는 innerFunc 이 없기 때문에 에러가 납니다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흔히 사용하는 이벤트핸들러를 기준으로 예시를 하나 더 들어 봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1726886217907&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function handle() {   
    console.log(this);  // 첫번째 ?, 두번째 ? 
}  
document
    .getElementsByTagName('body')[0]
    .addEventListener('click', handle);  // 첫번째. 호출되었다고 가정.
handle();  // 두번째. 첫번째 이후에 호출되었다고 가정.&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;다시 한번 강조하지만 this를 발화 지점 기준으로 생각하면 헷갈리지 않습니다.&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;700&quot; data-origin-height=&quot;478&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPLHSK/btsJHWZ9UZr/WyQiqj32PcmOmFgfiK0nh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPLHSK/btsJHWZ9UZr/WyQiqj32PcmOmFgfiK0nh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPLHSK/btsJHWZ9UZr/WyQiqj32PcmOmFgfiK0nh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPLHSK%2FbtsJHWZ9UZr%2FWyQiqj32PcmOmFgfiK0nh0%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;700&quot; height=&quot;478&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;478&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;span style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot;&gt;addEventListener 함수는 해당 엘리먼트에 콜백을 등록하는 함수입니다. &lt;br /&gt;간단하게 얘기하면 &lt;b&gt;&amp;lsquo;div&amp;rsquo; 객체에 &amp;lsquo;handle&amp;rsquo; 메서드를 등록&lt;/b&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; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;b2d9&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;1번 : 브라우저에서 div를 클릭하면 엔진이 반응합니다&lt;/li&gt;
&lt;li id=&quot;eec1&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;2번 : 해당 엘리먼트(div)에 등록된 event listener 들을 실행하라는 메시지를 보냅니다&lt;/li&gt;
&lt;li id=&quot;5a51&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;3번 : div 엘리먼트에서 handle을 발화합니다.&lt;/li&gt;
&lt;li id=&quot;5206&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;4번 : 이때 handle의 실행문맥의 this는 발화한 div 를 가리킵니다.&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;pre id=&quot;code_1726886361178&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var value = 1;

var obj = {
  value: 100,
  foo: function() {
    setTimeout(function() {
      console.log(&quot;callback's this: &quot;,  this);  // ?
      console.log(&quot;callback's this.value: &quot;,  this.value);  // ?
      function bar() {
        console.log(&quot;bar's this: &quot;, this);  // ?
      }
      bar();
    }, 1000);
  }
};

obj.foo();&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;this 는 무엇이 될까요?&lt;/p&gt;
&lt;p id=&quot;0e3c&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;7L : 브라우저 라면 window를 가리킵니다. 하지만 node.js 라면? 재밌게도 Timer 란 객체를 가리킵니다. setTimeout에 대한 구현이 다른 거죠. node.js 에서는 setTimeout 시 Timer 객체에 등록하고 해당 tick 이 되면 Timer에 실행하라는 메시지를 보내나 봅니다. 중요한 점은, 같은 코드여도 돌아가는 엔진마다 다를 수 있다는 의미인 것 같습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p id=&quot;69e3&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;8L : 브라우저라면 1, node.js 라면 undefined 가 나옵니다. 기본 this 는 global 라고 외우면 안되는 이유입니다&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p id=&quot;cbcd&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;9L : 당연하게도 브라우져라면 window, node.js 면 global을 가리킵니다. 엔진이 어떤 방식으로 실행했는지를 기억하시면 됩니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;마무리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로토타입은 &quot;클래스&quot;의 다른 구현이 아닌 완전히 새로운 철학하에 만들어진 이론입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 차이점을 이해한다면 더 이상 호이스팅, this, 렉시컬 스코프 등은 암기 과목이 아니게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트는 class, arrow function, let, const 등 여타 일반적인 언어와 보편성을 맞추고 있고,&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;이것들은 언어적 지원이 아닌 syntactic sugar인 부분도 언어의 근본적 구조가 다르기 때문을 이해할 수 있게 되면 좋겠습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;출처&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://medium.com/@limsungmook/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%8A%94-%EC%99%9C-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85%EC%9D%84-%EC%84%A0%ED%83%9D%ED%96%88%EC%9D%84%EA%B9%8C-997f985adb42&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://medium.com/@limsungmook/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%8A%94-%EC%99%9C-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85%EC%9D%84-%EC%84%A0%ED%83%9D%ED%96%88%EC%9D%84%EA%B9%8C-997f985adb42&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>javascript</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/232</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EA%B0%80-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85%EC%9D%84-%EC%84%A0%ED%83%9D%ED%95%9C-%EC%9D%B4%EC%9C%A0#entry232comment</comments>
      <pubDate>Sat, 21 Sep 2024 11:45:50 +0900</pubDate>
    </item>
    <item>
      <title>SAA/2024-09-18</title>
      <link>https://hmk1022.tistory.com/entry/SAA2024-09-18</link>
      <description>&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;ex) 모든 single point component 장애 시에 대응하기 위해서 설계되었다.&lt;/p&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;size18&quot;&gt;&lt;b&gt;높은 가용성을 제공하기 위해 컴퓨터 자원을 몇 개의 Availabilty Zone이 제공되어야하는가?&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;모든 고객들은 낮은 latency를 요규하기 때문에 AWS에서 지원할 수 있는 것은?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; High availablity&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; latency 즉 패킷의 출발지점부터 도착지까지의 시간을 줄이기 위해 고가용성( High availablity)을 제공해야한다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt; AWS 클라우드의 멀티 리전의 예제는?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Agility(민첩성)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; aws의 다중 리전 애플리케이션은 내결함성이 뛰어나며 장애 발생 시에 백업 리전으로 간편하고 빠르게 장애를 해결함&lt;/p&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; AWS 리전, 가용 영역, 엣지 로케이션에 대한 설명으로 올바른 것은?&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;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;b&gt;On-Demand 비용보다 예약 인스턴스 가격 모델이 평균적으로 비용을 줄이는 것은?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Three-year, All Upfront Standard RI pricing&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; RI(Reserved Instance)는 예약 인스턴스를 의미하고 3년간 모두 선결제(All Upfront) 하는 것이 가장 저렴하다.&lt;/p&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; 시스템의 성능을 제공하고 사용자들의 비용을 절감할 수 있도록 AWS 환경을 조사하여 기회를 찾아 제공하는 AWS 서비스는?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS Cost Explorer&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;On-Premise의 TCO와 AWS TCO를 비교할 때 포함해야 하는 비용은?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Project Management&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; TCO(Total Cost Ownership)는 총 비용을 의미하는 것으로 프로젝트 관리 비용도 포함되어야 한다.&lt;/p&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;전통적이고 가상화된 데이터 센터와 AWS를 비교해서 AWS의 비용적 효과는?&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;gt; AWS는 비용 변화의 요소가 적고 이상적으로 비용이 변화하면 기계학습을 통해서 이상 감지하여 클라우드 서비스 사용자에게 알려준다.&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;b&gt; Amazon EC2 인스턴스의 가격 모델에서 90% 정도의 금액을 절감할 수 있는 것은?&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;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;b&gt;AWS EC2 가격 모델 중 고개들의 Server bound software licenses가 있는 경우 어느 것을 사용해야 하나?&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;gt; Server bound software licenses라는 것은 서버와 관련한 전용 라이선스가 있다는 것이고, 이때는 전용 호스트를 사용&lt;/p&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;b&gt;기업은 AWS의 어떤 기능 또는 서비스를 사용해서 상세 수준의 지출을 추적하고 서비스 할 수 있는가?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AWS Budgets&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; AWS Budgets는 유동적인 예상 및 예측 기능을 사용해 비용계획을 수립하거나 관리함&lt;br /&gt;&lt;br /&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;b&gt;AWS Cloudtrail은 AWS 계정에 대한 규정 준수, 운영, 위험을 감시하는 서비스로 사용자 AWS 서비스에 대해서 수행한 작업은&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Cloudtrail의 이벤트에 모두 기록도니다. 기록되는 이벤트는 AWS SDK 및 API 호출 등이다.&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;AWS 모범사례에 따라 AWS에서 개발되는 애플리케이션은 어떻게 생성해야 하는가?&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;size16&quot;&gt;&lt;b&gt;AWS 리전을 선택할 때 고려해야할 사항&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가격, 서비스 가용성 및 규정 준수, 지연시간&lt;br /&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;b&gt;리전은 가용 영역들의 묶음이고 가용 영역은 데이터센터의 묶음이다&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AWS 리전은 고가용성을 위해 가용 영역의 클러스터이고 가용 영역은 데이터 센터의 클러스터이다.&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;리전&lt;/b&gt;은 &lt;b&gt;지역 단위의 큰 그룹&lt;/b&gt;입니다. (예: 서울, 도쿄, 뉴욕)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;가용 영역&lt;/b&gt;은 그 지역 안에 있는 &lt;b&gt;작은 그룹들&lt;/b&gt;입니다. 가용 영역 하나는 &lt;b&gt;여러 데이터 센터&lt;/b&gt;로 이루어져 있습니다.&lt;/li&gt;
&lt;li&gt;AWS는 이렇게 지역을 나누고 그 안에 물리적으로 분리된 데이터 센터들을 묶어서 고가용성(장애에 대비해 시스템을 계속 운영할 수 있는 능력)을 보장합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &lt;b&gt;리전은 여러 가용 영역이 모인 큰 그룹이고, 가용 영역은 실제 데이터 센터가 모여 있는 작은 그룹&lt;/b&gt;이라고 보면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;&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;b&gt;고가용성을 달성하기 위해서 몇 개의 가용영역에 컴퓨팅 리소스를 제공해야 하는가?&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클라우드 AWS 자격증으로 시작하기 69p&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>aws</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/231</guid>
      <comments>https://hmk1022.tistory.com/entry/SAA2024-09-18#entry231comment</comments>
      <pubDate>Wed, 18 Sep 2024 18:57:53 +0900</pubDate>
    </item>
    <item>
      <title>AWS Certified Solutions Architect - Associate(SAA) 오답 및 해설 2024-09-08</title>
      <link>https://hmk1022.tistory.com/entry/AWS-Certified-Solutions-Architect-AssociateSAA-%EC%98%A4%EB%8B%B5-%EB%B0%8F-%ED%95%B4%EC%84%A4-2024-09-08</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GcsrH/btsJuzrgDSo/gDDu8MkRXkCW0LIzgk0y2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GcsrH/btsJuzrgDSo/gDDu8MkRXkCW0LIzgk0y2k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GcsrH/btsJuzrgDSo/gDDu8MkRXkCW0LIzgk0y2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGcsrH%2FbtsJuzrgDSo%2FgDDu8MkRXkCW0LIzgk0y2k%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;1280&quot; height=&quot;384&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;384&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;한 회사에서 새 Amazon EC2 인스턴스에 새 데이터베이스를 배포하고 있습니다. 이 &lt;b&gt;데이터베이스의 워크로드에는 최대 20,000IOPS를 지원할 수 있는&lt;/b&gt; 단일 Amazon Elastic Block Store(Amazon EBS) 볼륨이 필요합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 요구 사항을 충족하는 EBS 볼륨 유형은 무엇인가요?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;문제는 이런 상황이에요:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당신은 웹 애플리케이션에서 &lt;b&gt;새로운 서버&lt;/b&gt;를 세팅해서, &lt;b&gt;데이터베이스&lt;/b&gt;를 연결하려고 해요. 근데, 이 데이터베이스가 데이터를 빠르게 읽고 쓰기 위해서 &lt;b&gt;엄청나게 많은 처리량&lt;/b&gt;(최대 20,000 IOPS)이 필요해요. 여기서 &lt;b&gt;IOPS&lt;/b&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;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;프로비저닝된 IOPS SSD (정답)&lt;/b&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;b&gt;64,000 IOPS&lt;/b&gt;까지 지원되니까, 당신이 요구하는 20,000 IOPS를 충분히 만족시켜요. &lt;b&gt;고성능 데이터 처리&lt;/b&gt;에 적합한 옵션이에요.&lt;/li&gt;
&lt;li&gt;**프로비저닝(provisioning)**은 쉽게 말해 &lt;b&gt;필요한 리소스를 미리 준비해 놓는 것&lt;/b&gt;을 뜻해요. 컴퓨팅 리소스, 저장소, 네트워크 등 필요한 자원을 사전에 할당하는 개념이죠.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;처리량 최적화 HDD&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이건 느려요. &lt;b&gt;500 IOPS&lt;/b&gt;밖에 안 돼서, 요구사항인 20,000 IOPS와는 거리가 멀어요. &lt;b&gt;대용량 데이터를 천천히 처리&lt;/b&gt;하는데 적합해요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;범용 SSD&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;범용 SSD는 &lt;b&gt;보통 수준의 성능&lt;/b&gt;을 제공해요. 최대 &lt;b&gt;16,000 IOPS&lt;/b&gt;까지 지원하지만, 문제에서 필요한 20,000 IOPS를 못 따라가요. &lt;b&gt;일반적인 작업&lt;/b&gt;에 적합하지만, 고성능이 필요한 상황에선 부족해요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;콜드 HDD&lt;/b&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;b&gt;저장해두는 용도&lt;/b&gt;로 적합해요. IOPS보다는 대용량 파일을 저장하는 데 초점이 맞춰져 있어요.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;요약:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당신의 데이터베이스는 &lt;b&gt;빠른 속도로 많은 양의 데이터를 처리&lt;/b&gt;해야 하니까, &lt;b&gt;가장 빠르고 강력한 성능&lt;/b&gt;을 제공하는 &lt;b&gt;프로비저닝된 IOPS SSD&lt;/b&gt;가 정답이에요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;한 회사에서 솔루션스 아키텍트에게 기존&lt;b&gt; 온프레미스 애플리케이션에 대한 파일럿 라이트 재해 복구(DR) 전략&lt;/b&gt;을 구현하도록 요청합니다. 애플리케이션은 독립적으로 실행되며 데이터베이스에 액세스할 필요가 없습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다음 중 &lt;b&gt;파일럿 라이트 DR 전략을 구현하는 솔루션&lt;/b&gt;은 무엇입니까?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 문제에서 정답은 &lt;b&gt;B. Amazon EC2 인스턴스를 사용하여 AWS에 애플리케이션 호스팅 환경을 다시 생성하고 EC2 인스턴스를 중지&lt;/b&gt;하는 옵션입니다. 파일럿 라이트 DR 전략과 다른 선택지가 왜 오답인지 쉽게 풀어서 설명해볼게요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정답:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;B. Amazon EC2 인스턴스를 사용하여 AWS에 애플리케이션 호스팅 환경을 다시 생성하고 EC2 인스턴스를 중지&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;파일럿 라이트 DR 전략&lt;/b&gt;의 핵심은 AWS에 &lt;b&gt;미리 중요한 인프라&lt;/b&gt;를 준비해 두고, 평소에는 최소한의 리소스만 실행시키며, 문제가 발생할 때만 전체 시스템을 가동하는 방식이에요.&lt;/li&gt;
&lt;li&gt;즉, 미리 AWS에 애플리케이션 환경을 설정해두고, 장애가 생기면 &lt;b&gt;EC2 인스턴스를 빠르게 켜서&lt;/b&gt; 애플리케이션을 정상적으로 돌리면 돼요. 복구 시간도 짧고, 비상시에만 자원을 사용해서 비용도 절감할 수 있어요.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;오답:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A. 온프레미스 애플리케이션, 구성 및 데이터를 Amazon S3 버킷에 백업&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;백업 및 복원 DR 전략&lt;/b&gt;이에요. S3에 데이터를 백업하는 건 좋지만, 장애가 발생하면 &lt;b&gt;AWS에서 새 환경을 구축하고 데이터를 복원하는 데 시간이 오래 걸려요&lt;/b&gt;. 복구 시간이 몇 시간에서 며칠 걸릴 수 있어요. 비용은 적지만 속도가 느려서 긴급 상황에 적합하지 않아요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;C. EC2 인스턴스에서 애플리케이션 트래픽의 10%를 처리&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;웜 스탠바이 DR 전략&lt;/b&gt;이에요. 이미 AWS에서 애플리케이션의 일부 트래픽을 처리하고 있어서 장애가 발생하면 바로 전체 트래픽을 AWS로 넘길 수 있지만, &lt;b&gt;리소스가 계속 실행 중&lt;/b&gt;이라 비용이 높아요. 파일럿 라이트보다는 &lt;b&gt;비용이 더 들지만 복구는 빠릅니다&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;D. 온프레미스 환경을 다시 구축하고 S3에서 복원&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;백업 및 복원 DR 전략&lt;/b&gt;이에요. 온프레미스 인프라를 다시 설정하고 S3에서 데이터를 복원하는 건 시간이 오래 걸려요. &lt;b&gt;온프레미스 환경에서 복구하는 데 시간이 많이 소요&lt;/b&gt;되므로 긴급한 상황에서는 부적합해요.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;요약:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일럿 라이트 DR 전략은 AWS에 미리 애플리케이션을 설정해 두고, &lt;b&gt;문제가 생기면 빠르게 가동&lt;/b&gt;하는 방법이에요. &lt;b&gt;필요한 리소스만 최소한으로 유지&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엄격한 데이터 보호 요구 사항이 있는 한 회사가 있습니다. 솔루션스 아키텍트는 인터넷에서 백엔드 Amazon RDS DB 인스턴스에 액세스할 수 없도록 VPC에 대한 보안을 구성해야 합니다. 또한 솔루션스 아키텍트는 애플리케이션 티어에서 지정된 포트를 통해서만 DB 인스턴스에 액세스할 수 있는지 확인해야 합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;솔루션스 아키텍트는 이러한 요구 사항을 충족하기 위해 어떤 조치를 취해야 하나요? (정답은 2개입니다.)&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; 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;br /&gt;이 문제의 정답은 &lt;b&gt;A. DB 인스턴스를 프라이빗 서브넷에 배치&lt;/b&gt;와 &lt;b&gt;E. 애플리케이션 티어의 요청을 허용하는 인바운드 규칙을 설정&lt;/b&gt;입니다. 이제 각각의 이유와 다른 선택지가 왜 오답인지 쉽게 설명해볼게요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정답:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A. DB 인스턴스에 대한 프라이빗 서브넷만 포함하는 DB 서브넷 그룹을 지정&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;프라이빗 서브넷&lt;/b&gt;은 인터넷과 연결되지 않은 내부 네트워크 공간이에요. 데이터베이스를 &lt;b&gt;프라이빗 서브넷&lt;/b&gt;에 배치하면 외부에서 직접 접근할 수 없게 되기 때문에, &lt;b&gt;보안이 강화&lt;/b&gt;돼요. 인터넷으로부터 DB를 보호하는 첫 번째 조치입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;E. 애플리케이션 티어의 보안 그룹에서 특정 포트를 통한 인바운드 요청 허용&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;데이터베이스 포트에 대해서만 애플리케이션 티어에서 들어오는 요청을 허용&lt;/b&gt;하고, 그 외의 트래픽은 차단하는 방식으로 설정해요. 이를 통해 애플리케이션에서만 DB에 접근할 수 있게 하고, &lt;b&gt;허용되지 않은 트래픽을 막아&lt;/b&gt; 보안을 강화할 수 있어요.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;오답:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;B. 프라이빗 IPv4 주소를 사용한 탄력적 네트워크 인터페이스 연결&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;**탄력적 네트워크 인터페이스(ENI)**는 네트워크 설정을 유연하게 변경할 수 있게 도와주는 도구이지만, 여기서는 DB 인스턴스를 보호하는 방법과 직접적인 관련이 없어요. 네트워크 카드와 관련된 기능일 뿐, DB 보안을 크게 향상시키지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;C. VPC에서 AWS Shield를 구성하고 서브넷의 라우팅 테이블 업데이트&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;AWS Shield&lt;/b&gt;는 DDoS(분산 서비스 거부) 공격을 막는 서비스지만, 라우팅 테이블과 관련된 설정은 이 문제에서 요구하는 데이터베이스 보안과는 거리가 있어요. DDoS 공격에 대한 보호는 DB 액세스 제어와 관련이 없어요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;D. Direct Connect 연결 구성&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;AWS Direct Connect&lt;/b&gt;는 온프레미스 데이터 센터와 AWS 클라우드 간에 &lt;b&gt;전용 네트워크 연결&lt;/b&gt;을 제공하는 서비스에요. 하지만 문제에서는 애플리케이션과 DB 간의 액세스 제어에 대해 묻고 있으며, Direct Connect는 여기서 요구하는 보안 문제와 관련이 없어요.&lt;/li&gt;
&lt;/ul&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;b&gt;프라이빗 서브넷&lt;/b&gt;에 DB를 배치하면 외부에서 접근할 수 없어서 보안이 강화됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보안 그룹 규칙&lt;/b&gt;을 통해 애플리케이션 티어만 DB에 접근할 수 있도록 특정 포트를 제한하면 보안이 더 높아져요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두 가지 조치가 &lt;b&gt;인터넷 접근 차단&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 회사에서 Amazon CloudFront 배포를 위한 원본으로 구성된 Application Load Balancer를 사용하여 Amazon EC2 인스턴스에서 웹 사이트를 실행합니다. 이 회사는 &lt;b&gt;크로스 사이트 스크립팅 및 SQL 명령어 삽입 공격으로부터 보호&lt;/b&gt;하려고 합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; 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;br /&gt;&lt;br /&gt;이 문제에서 정답은 &lt;b&gt;D. CloudFront 배포에서 AWS WAF를 설정하고 크로스 사이트 스크립팅 및 SQL 명령어 삽입 공격을 차단하는 조건 및 규칙을 사용&lt;/b&gt;입니다. 각 선택지가 왜 정답 또는 오답인지 자세히 설명해볼게요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정답:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;D. CloudFront 배포에서 AWS WAF를 설정하고 크로스 사이트 스크립팅 및 SQL 명령어 삽입 공격을 차단하는 조건 및 규칙을 사용&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;**AWS WAF(Web Application Firewall)**는 웹 애플리케이션을 보호하는 데 사용되는 서비스로, **크로스 사이트 스크립팅(XSS)**이나 &lt;b&gt;SQL 삽입&lt;/b&gt;과 같은 악의적인 공격을 감지하고 차단할 수 있어요.&lt;/li&gt;
&lt;li&gt;WAF를 CloudFront와 함께 사용하면, &lt;b&gt;웹 트래픽을 필터링하고 보안 규칙을 설정&lt;/b&gt;하여 이런 종류의 공격을 방어할 수 있습니다.&lt;/li&gt;
&lt;li&gt;따라서, WAF를 사용해 해당 요구 사항을 가장 잘 충족시킬 수 있어요.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;오답:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A. AWS Shield Advanced를 활성화하고 CloudFront 배포를 보호된 리소스로 나열&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;AWS Shield Advanced&lt;/b&gt;는 &lt;b&gt;DDoS(분산 서비스 거부) 공격&lt;/b&gt;으로부터 보호하는 서비스입니다. 하지만 **크로스 사이트 스크립팅(XSS)**이나 &lt;b&gt;SQL 삽입&lt;/b&gt; 공격을 방어하지는 않아요.&lt;/li&gt;
&lt;li&gt;Shield는 트래픽 볼륨을 기반으로 한 공격에 집중하기 때문에, XSS나 SQL 삽입 같은 &lt;b&gt;애플리케이션 계층&lt;/b&gt;의 공격에는 적합하지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;B. AWS Firewall Manager에서 크로스 사이트 스크립팅 및 SQL 명령어 삽입 공격을 차단하도록 AWS Shield Advanced 정책을 정의&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;AWS Firewall Manager&lt;/b&gt;는 여러 계정과 리소스에서 WAF, Shield Advanced 등을 중앙에서 관리할 수 있는 도구예요. 그러나 여기서도 &lt;b&gt;Shield Advanced&lt;/b&gt;는 DDoS 방어에만 집중하므로 &lt;b&gt;XSS&lt;/b&gt;나 &lt;b&gt;SQL 삽입&lt;/b&gt;에 대한 방어는 제공하지 않습니다.&lt;/li&gt;
&lt;li&gt;따라서 Firewall Manager 자체는 이런 요구 사항을 해결하지 못해요.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;C. EC2 인스턴스에 AWS Firewall Manager를 배포하고 크로스 사이트 스크립팅 및 SQL 명령어 삽입 공격을 차단하는 조건 및 규칙을 생성&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;AWS Firewall Manager&lt;/b&gt;는 &lt;b&gt;AWS 관리형 서비스&lt;/b&gt;로, EC2 인스턴스에 설치하는 방식이 아닙니다. 또한 Firewall Manager는 AWS WAF나 Shield Advanced 같은 도구를 &lt;b&gt;관리하는 용도&lt;/b&gt;이기 때문에, 이 방식으로는 직접적인 보안을 제공할 수 없어요.&lt;/li&gt;
&lt;li&gt;이 옵션은 기술적으로 잘못된 방식입니다.&lt;/li&gt;
&lt;/ul&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;b&gt;AWS WAF&lt;/b&gt;는 &lt;b&gt;크로스 사이트 스크립팅(XSS)&lt;/b&gt; 및 &lt;b&gt;SQL 삽입&lt;/b&gt; 공격을 막을 수 있는 도구로, 문제의 요구 사항을 가장 적절하게 충족합니다.&lt;/li&gt;
&lt;li&gt;다른 서비스들, 특히 &lt;b&gt;AWS Shield Advanced&lt;/b&gt;는 주로 &lt;b&gt;DDoS 공격 방어&lt;/b&gt;에 초점을 맞추고 있어, 애플리케이션 계층에서 발생하는 보안 문제(예: XSS, SQL 삽입)를 해결하는 데 적합하지 않습니다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;한 회사가 EC2 Auto Scaling 그룹의 일부인 대규모 범용 Amazon EC2 인스턴스 유형에서 실행되는 애플리케이션을 보유하고 있습니다. 이 회사는 이 애플리케이션과 관련된 향후 &lt;b&gt;비용을 줄이려고 합니다&lt;/b&gt;. 회사는 Amazon CloudWatch의 지표와 로그를 검토한 후, 애플리케이션이 &lt;b&gt;무작위로 하루에 수회 실행&lt;/b&gt;되어 데이터를 검색하고 관리한다는 사실을 알게 되었습니다. CloudWatch에 따르면 &lt;b&gt;각 요청의 최대 런타임은 10분이고 메모리 사용량은 4GB이며 인스턴스는 항상 실행 상태&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제에서 가장 비용을 절감할 수 있는 솔루션은 &lt;b&gt;B. 애플리케이션 코드를 리팩터링하여 AWS Lambda 함수로 실행&lt;/b&gt;입니다. 각 선택지에 대해 설명해 드릴게요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정답:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;B. 애플리케이션 코드를 리팩터링하여 AWS Lambda 함수로 실행합니다.&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;AWS Lambda&lt;/b&gt;는 &lt;b&gt;서버리스 컴퓨팅&lt;/b&gt; 서비스로, &lt;b&gt;요청이 있을 때만 실행되며 실행 시간이 끝나면 자동으로 종료&lt;/b&gt;됩니다. 이 애플리케이션은 짧은 시간 동안 불규칙하게 실행되므로, 항상 실행 상태인 EC2 인스턴스를 사용하는 것보다 Lambda로 리팩터링하면 비용을 크게 절감할 수 있습니다. Lambda는 &lt;b&gt;필요한 만큼만 실행&lt;/b&gt;되기 때문에 EC2 인스턴스 상시 실행으로 발생하는 &lt;b&gt;불필요한 비용을 절감&lt;/b&gt;할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;오답:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A. 용량 확장이 가능한 대규모 EC2 인스턴스에 애플리케이션을 배포합니다.&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;EC2 인스턴스는 항상 실행 상태여야 하므로 비용 절감에 효과적이지 않습니다. 사용량이 불규칙한 경우에는 &lt;b&gt;EC2 인스턴스 상시 실행&lt;/b&gt;이 불필요한 비용을 초래할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;C. Amazon Elastic Kubernetes Service(Amazon EKS)를 사용하여 애플리케이션을 컨테이너화합니다. EC2 인스턴스에서 컨테이너를 호스팅합니다.&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;EKS&lt;/b&gt;는 애플리케이션을 컨테이너화할 수 있지만, &lt;b&gt;EC2 인스턴스가 상시 실행&lt;/b&gt;되어야 하므로 비용 절감에는 적합하지 않습니다. 이 경우 컨테이너화로 얻는 이점이 크지 않고, 서버리스 아키텍처가 더 나은 선택입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;D. AWS Instance Scheduler를 사용하여 로그의 런타임을 기반으로 인스턴스를 시작 및 중지합니다.&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;Instance Scheduler&lt;/b&gt;는 미리 정의된 시간에 맞춰 인스턴스를 시작/중지하는 방식이므로, 무작위로 실행되는 애플리케이션에는 적합하지 않습니다. 이 솔루션은 &lt;b&gt;정확한 실행 시간을 예측할 수 없을 때&lt;/b&gt; 효과적이지 않으며, 인스턴스를 너무 자주 시작/중지하면 비용 절감 효과가 미미할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;요약:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Lambda는 &lt;b&gt;필요할 때만 실행되고 짧은 실행 시간에 적합&lt;/b&gt;한 서버리스 서비스이기 때문에, 이 시나리오에서 비용을 가장 절감할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 회사에서 애플리케이션 계층과 온라인 트랜잭션 처리(OLTP) 관계형 데이터베이스로 구성될 새 애플리케이션을 배포하고 있다. 이 &lt;b&gt;애플리케이션은 항상 사용 가능&lt;/b&gt;해야 한다. 하지만 애플리케이션에는 &lt;b&gt;예측할 수 없는 트래픽 패턴이 존재&lt;/b&gt;할 수 있다. 회사는 이러한 &lt;b&gt;유휴 기간 동안 발생하는 컴퓨팅 비용을 최소화&lt;/b&gt;하고자 한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다음 중 이러한 요구 사항을 가장 비용 효율적으로 충족하는 솔루션은 무엇인가?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 문제에서 가장 비용 효율적인 솔루션은 &lt;b&gt;D. AWS Fargate에서 Amazon Elastic Container Service(Amazon ECS)를 사용하는 컨테이너를 통해 애플리케이션을 실행한다. 데이터베이스에 Amazon Aurora Serverless를 사용한다&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;정답:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;D. AWS Fargate에서 Amazon ECS를 사용하는 컨테이너를 통해 애플리케이션을 실행하고, 데이터베이스에 Amazon Aurora Serverless를 사용합니다.&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;AWS Fargate&lt;/b&gt;는 &lt;b&gt;서버리스&lt;/b&gt; 컨테이너 서비스로, 애플리케이션이 실행 중일 때만 리소스를 사용하므로, &lt;b&gt;유휴 상태일 때 발생하는 비용을 최소화&lt;/b&gt;할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Amazon Aurora Serverless&lt;/b&gt;는 &lt;b&gt;자동으로 확장&lt;/b&gt;하고, 유휴 상태일 때는 비용이 발생하지 않으므로, 트래픽 패턴이 예측 불가능한 환경에서도 &lt;b&gt;효율적인 비용 관리&lt;/b&gt;가 가능합니다. 이 솔루션은 &lt;b&gt;필요할 때만 리소스를 사용&lt;/b&gt;하고, 유휴 시간에는 비용을 줄일 수 있기 때문에 &lt;b&gt;비용 효율적&lt;/b&gt;입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;**ECS (Amazon Elastic Container Service)**는 AWS에서 제공하는 &lt;b&gt;컨테이너 오케스트레이션 서비스&lt;/b&gt;입니다. ECS를 사용하면 컨테이너화된 애플리케이션을 쉽게 배포, 관리, 확장할 수 있습니다. 사용자가 관리하는 EC2 인스턴스 또는 AWS에서 제공하는 서버리스 방식으로 컨테이너를 실행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Fargate&lt;/b&gt;는 &lt;b&gt;ECS나 EKS&lt;/b&gt;에서 컨테이너를 실행할 때, &lt;b&gt;서버를 관리할 필요 없이&lt;/b&gt; 자동으로 리소스를 할당하는 서버리스 컴퓨팅 엔진입니다. 즉, &lt;b&gt;인프라 관리 없이&lt;/b&gt; 애플리케이션의 컨테이너만 실행하면 되며, AWS가 필요한 컴퓨팅 자원을 자동으로 관리해줍니다. 이를 통해 유휴 리소스 비용을 줄이고, 서버 관리 부담을 덜 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;오답:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A. 버스트 가능 인스턴스 유형을 사용하여 Amazon EC2 인스턴스에서 애플리케이션을 실행한다. 데이터베이스에 Amazon Redshift를 사용한다.&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;EC2 버스트 가능 인스턴스&lt;/b&gt;는 &lt;b&gt;트래픽이 증가할 때만 성능이 일시적으로 향상&lt;/b&gt;되지만, 트래픽이 적을 때도 &lt;b&gt;유휴 리소스 비용이 발생&lt;/b&gt;합니다. 또한, &lt;b&gt;Amazon Redshift&lt;/b&gt;는 &lt;b&gt;OLTP&lt;/b&gt; 용도가 아닌 &lt;b&gt;OLAP&lt;/b&gt;(온라인 분석 처리)에 최적화되어 있어 적합하지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;B. AWS CloudFormation을 사용하여 Amazon EC2 인스턴스에 애플리케이션과 MySQL 데이터베이스를 배포한다. 유휴 기간이 시작될 때 인스턴스를 삭제한다.&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;CloudFormation&lt;/b&gt;은 인프라를 자동으로 관리할 수 있지만, &lt;b&gt;유휴 상태에서 인스턴스를 삭제&lt;/b&gt;하는 것은 &lt;b&gt;항상 사용 가능&lt;/b&gt;해야 하는 요구 사항에 부합하지 않으며, 데이터베이스 삭제 시 &lt;b&gt;데이터 손실&lt;/b&gt; 위험이 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;C. Application Load Balancer 기반의 Auto Scaling 그룹에 속한 Amazon EC2 인스턴스에서 애플리케이션을 배포한다. 데이터베이스에 Amazon RDS for MySQL을 사용한다.&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;Auto Scaling&lt;/b&gt;을 통해 트래픽에 따라 인스턴스를 동적으로 조정할 수 있지만, &lt;b&gt;항상 최소한 하나의 EC2 인스턴스와 RDS 인스턴스가 실행&lt;/b&gt;되어야 하므로 &lt;b&gt;유휴 시간 동안 비용 절감이 어렵습니다&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;요약:&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;AWS Fargate&lt;/b&gt;와 &lt;b&gt;Amazon Aurora Serverless&lt;/b&gt; 조합은 트래픽 변화에 유연하게 대응할 수 있으며, 유휴 상태에서는 비용이 거의 발생하지 않으므로 &lt;b&gt;비용 효율성&lt;/b&gt; 면에서 가장 적합한 선택입니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;단점으로 Cold Start Latency (냉시작 지연), 비용 예측의 어려움, 컨테이너 상태 관리, 데이터베이스 연결 제한 등이 있을 수 있음&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;한 회사가 Amazon EC2 기반 MariaDB 데이터베이스를 Amazon RDS로 전환하고 있다. 이 회사는 자사의 CPU 및 메모리 요구 사항을 충족할 데이터베이스 인스턴스 유형을 이미 파악했다. &lt;b&gt;데이터베이스는 최소 40GiB의 스토리지 용량과 1,000IOPS를 제공&lt;/b&gt;해야 한다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다음 중 가장 비용 효율적인 Amazon RDS for MariaDB 인스턴스 스토리지 구성은 무엇인가?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;여기서 주어진 요구 사항에 맞는 가장 비용 효율적인 Amazon RDS for MariaDB 인스턴스 스토리지 구성은 다음과 같습니다:&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정답: B&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;RDS 인스턴스에 50GiB의 범용 SSD(gp3) 스토리지를 프로비저닝한다.&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;범용 SSD(gp3)&lt;/b&gt; 스토리지는 &lt;b&gt;IOPS&lt;/b&gt;를 볼륨 크기와 관계없이 &lt;b&gt;3,000 IOPS&lt;/b&gt;를 지원합니다.&lt;/li&gt;
&lt;li&gt;이 스토리지 타입은 &lt;b&gt;IOPS와 스토리지 용량&lt;/b&gt;의 관계가 단순하여 예측 가능한 비용을 제공합니다.&lt;/li&gt;
&lt;li&gt;비용 효율적으로 높은 IOPS를 지원하며, 필요한 1,000 IOPS를 초과하는 성능을 제공하면서도 추가 비용이 발생하지 않습니다.&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;b&gt;A&lt;/b&gt; (350GiB의 마그네틱 스토리지): 마그네틱 스토리지는 IOPS를 직접적으로 프로비저닝할 수 없으며, 성능이 일관되지 않아서 요구 사항을 충족할 수 없습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C&lt;/b&gt; (334GiB의 범용 SSD(gp2) 스토리지): gp2는 IOPS가 볼륨 크기에 따라 비례하여 증가하며, 필요한 1,000 IOPS를 만족시키기 위해 334GiB의 스토리지가 필요합니다. 이는 gp3보다 더 비쌉니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;D&lt;/b&gt; (1,000IOPS의 50GiB 프로비저닝된 IOPS 스토리지): 프로비저닝된 IOPS 스토리지는 IOPS를 정확히 제공하지만, gp3 스토리지보다 비용이 비쌉니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소 5년 동안 데이터 레코드를 유지 관리해야 하는 한 회사가 있습니다. &lt;b&gt;데이터는 저장된 후에 거의 액세스되지 않습니다. 데이터는 2시간 이내에 액세스할 수 있어야 합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 요구 사항을 가장 비용 효율적으로 충족할 수 있는 솔루션은 무엇인가요?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 시나리오에서 요구 사항에 가장 적합한 솔루션은 &lt;b&gt;Amazon S3와 S3 Glacier Instant Retrieval&lt;/b&gt;입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정답: D&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Amazon S3 버킷에 데이터를 저장하고 S3 수명 주기 정책을 사용하여 데이터를 S3 Glacier Instant Retrieval로 이동합니다.&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Amazon S3&lt;/b&gt;는 데이터 저장을 위한 경제적이고 확장 가능한 기본 스토리지 솔루션을 제공합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;S3 Glacier Instant Retrieval&lt;/b&gt;은 데이터가 거의 액세스되지 않지만 2시간 이내에 액세스해야 하는 경우에 적합한 비용 효율적인 아카이브 스토리지 솔루션입니다.&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;b&gt;A&lt;/b&gt; (Amazon EFS와 AWS Direct Connect): Amazon EFS는 파일 시스템 접근을 필요로 할 때 유용하지만, 장기 데이터 보관과 비용 효율성 측면에서 S3보다 비쌉니다. AWS Direct Connect는 네트워크 연결을 위한 옵션일 뿐, 데이터 보관과는 직접적인 연관이 없습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;B&lt;/b&gt; (Amazon EBS와 스냅샷): EBS는 일반적으로 블록 스토리지로 사용되며, 스냅샷을 S3로 이동하더라도 EBS는 비용 효율적인 데이터 장기 보관 솔루션이 아닙니다. S3와 비교할 때 비싼 옵션입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C&lt;/b&gt; (S3 Standard-IA): S3 Standard-IA는 데이터가 자주 액세스되지 않는 경우에 적합하지만, 더 긴 검색 시간이 필요한 경우에 비해 비용 효율적인 선택이 아닙니다. S3 Glacier Instant Retrieval이 이러한 요구 사항을 더 잘 충족합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-v-ad49d49a=&quot;&quot;&gt;
&lt;div id=&quot;content-question-start&quot; style=&quot;color: #000000;&quot;&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;위성 이미지를 처리하는 한 회사에 AWS에서 실행되는 애플리케이션이 있습니다. 이 회사에서는&lt;b&gt; Amazon S3 버킷에 이미지를 저장&lt;/b&gt;합니다. 규정 준수를 위해 &lt;b&gt;이 회사는 한 달에 한 번 모든 데이터를 온프레미스 위치로 복제해야 합니다.&lt;/b&gt; 회사에서 전송해야 하는 평균 데이터 양은 60TB입니다.&lt;/p&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;이 데이터를 전송하는 가장 비용 효율적인 방법은 무엇인가요?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&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;AWS Snowball Edge Storage Optimized 디바이스&lt;/b&gt;를 사용하는 것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;정답: A&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;기존 S3 버킷에서 AWS Snowball Edge Storage Optimized 디바이스로 매월 데이터를 내보냅니다. 그런 다음 온프레미스 위치로 디바이스를 배송하고 데이터를 전송합니다. 일주일 후에 디바이스를 반환합니다.&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;AWS Snowball Edge Storage Optimized&lt;/b&gt;는 대용량 데이터 전송을 위해 설계된 장비로, 60TB의 데이터를 경제적으로 전송하는 데 적합합니다.&lt;/li&gt;
&lt;li&gt;Snowball Edge는 데이터 전송 비용을 줄이는 데 도움을 주며, 온프레미스 위치로 데이터를 직접 전송할 수 있어 비용을 절감할 수 있습니다.&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;b&gt;B&lt;/b&gt; (S3 버킷 복제와 AWS Storage Gateway File Gateway 사용): S3 버킷 복제는 추가 비용이 발생하며, AWS Storage Gateway는 온프레미스와 클라우드 간 데이터 전송에 대한 추가 비용이 발생할 수 있습니다. Snowball Edge는 이러한 전송과 관련된 비용을 줄일 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C&lt;/b&gt; (S3 버킷 복제와 S3 데이터 전송): S3 Standard-IA 스토리지를 사용하는 새 버킷으로 복제한 후 온프레미스 위치로 전송하는 것은 추가 복제와 전송 비용이 발생하며, Snowball Edge는 이러한 복제와 전송을 효율적으로 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;D&lt;/b&gt; (CloudFront 배포): CloudFront는 데이터 전송을 위한 캐싱과 배포 네트워크를 제공하지만, 대량의 데이터를 온프레미스 위치로 전송하는 데 드는 비용이 Snowball Edge보다 훨씬 더 비쌀 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Snowball Edge는 대량의 데이터 전송을 위한 경제적이고 효율적인 솔루션을 제공합니다.&lt;/p&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 회사가 하나의 AWS 계정을 사용하여 프로덕션 워크로드를 실행한다. 이 &lt;b&gt;회사는 별도의 보안 팀용 AWS 계정을 가지고 있다.&lt;/b&gt; 보안 팀은 프로덕션 워크로드를 실행하는&lt;b&gt; AWS 계정의 특정 계정 설정 및 리소스 구성을 정기 감사 중에 확인해야 한다.&lt;/b&gt; 솔루션스 아키텍트는 AWS 보안 모범 사례를 따르는 솔루션을 설계하여 &lt;b&gt;보안 팀에 필요한 액세스 권한을 제공해야 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다음 중 이러한 요구 사항을 충족하는 솔루션은 무엇인가?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div data-message-id=&quot;74011639-3a7b-4eb8-873a-44ec05f7a301&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;정답: B&lt;/b&gt; 프로덕션 계정에 IAM 역할을 생성한다. 보안 팀에서 요구하는 권한을 제공하는 권한 정책을 연결한다. 보안 팀 계정을 신뢰 정책에 추가한다.&lt;/h4&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;IAM 역할과 신뢰 정책&lt;/b&gt;을 사용하는 것은 AWS의 보안 모범 사례를 따릅니다. 이 접근 방식은 보안 팀이 필요할 때만 프로덕션 계정의 리소스에 접근할 수 있도록 허용하며, 권한을 세밀하게 제어할 수 있습니다.&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;&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;A (IAM 사용자 생성 및 권한 부여):&lt;/b&gt; IAM 사용자를 직접 생성하여 권한을 부여하는 방식은 보안 모범 사례를 따르지 않으며, 역할을 사용하여 권한을 위임하는 방식보다 관리가 어렵습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C (IAM 사용자에 관리 권한 부여):&lt;/b&gt; IAM 사용자에게 관리 권한을 부여하는 것은 보안 원칙에 어긋나며, 관리 권한은 최소한으로 유지해야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;D (IAM 사용자와 IAM 그룹을 통한 권한 부여):&lt;/b&gt; IAM 그룹을 사용하는 방식은 역할을 사용하는 방식보다 세밀한 권한 관리가 어려울 수 있으며, 역할을 사용하는 방법이 더 적합합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 솔루션은 AWS에서 보안 및 권한 관리의 모범 사례를 따르며, 보안 팀이 프로덕션 환경에 안전하고 효율적으로 접근할 수 있도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;보고 애플리케이션이 &lt;b&gt;Application Load Balancer 기반의 Amazon EC2 인스턴스에서 실행&lt;/b&gt;된다. 인스턴스는 다수의 가용 영역에 속한 Amazon EC2 Auto Scaling 그룹에서 실행된다. 복잡한 보고서의 경우 애플리케이션이 &lt;b&gt;요청에 응답하는 데 최대 15분이 걸릴 수 있다.&lt;/b&gt; 한 솔루션스 아키텍트가 &lt;b&gt;축소 이벤트 중에 보고서 요청이 처리될 경우 사용자에게 HTTP 5xx 오류가 발생할 수 있다는 점을 우려&lt;/b&gt;하고 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span data-state=&quot;closed&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&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;b&gt;정답: D&lt;/b&gt; 대상 인스턴스 그룹의 등록 취소 지연의 제한 시간을 900초보다 크게 늘린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&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;b&gt;등록 취소 지연&lt;/b&gt;(deregistration delay)은 인스턴스가 Auto Scaling 그룹에서 종료되기 전에 인스턴스에서 진행 중인 요청을 완료할 수 있도록 대기하는 시간을 설정합니다. 기본값은 300초(5분)이며, 이를 900초(15분)으로 늘리면 요청이 완료될 때까지 인스턴스를 계속 유지하여 사용자에게 HTTP 5xx 오류가 발생하지 않도록 할 수 있습니다.&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;&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;A (스티키 세션 사용):&lt;/b&gt; 스티키 세션은 동일한 사용자 요청을 동일한 인스턴스로 라우팅하지만, 인스턴스가 종료되기 전에 진행 중인 요청을 완료하도록 보장하지는 않습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;B (인스턴스 크기 증가):&lt;/b&gt; 인스턴스 크기를 늘리는 것은 요청 처리 속도를 개선할 수 있지만, 인스턴스 종료 전 진행 중인 요청을 완료하는 문제를 직접적으로 해결하지는 않습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C (휴지 기간 연장):&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 회사에서 AWS에 배포할 채팅 애플리케이션을 개발하고 있습니다. 이 애플리케이션은 &lt;b&gt;키 값 데이터 모델을 사용하여 메시지를 저장&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 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 요구 사항을 충족하는 데이터베이스 솔루션은 무엇인가요?&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정답: B&lt;/b&gt; DynamoDB Accelerator(DAX)가 포함된 Amazon DynamoDB&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&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;b&gt;Amazon DynamoDB&lt;/b&gt;는 키-값 데이터 모델을 지원하는 NoSQL 데이터베이스로, 높은 읽기 성능을 제공합니다.&lt;/li&gt;
&lt;li&gt;**DynamoDB Accelerator (DAX)**는 DynamoDB의 인메모리 캐싱 서비스로, 마이크로초 단위의 응답 시간을 제공합니다. 이는 &lt;b&gt;높은 비율의 읽기 작업을 처리하는 데 매우 적합&lt;/b&gt;합니다.&lt;/li&gt;
&lt;li&gt;이 조합은 메시지를 빠르게 읽어야 하는 요구 사항을 충족하며, 대기 시간을 최소화할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&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;b&gt;A (Aurora 복제본이 포함된 Amazon Aurora):&lt;/b&gt; Aurora는 관계형 데이터베이스이며, 키-값 데이터베이스 모델을 사용하지 않습니다. 또한, 마이크로초 단위의 대기 시간을 제공하지 않습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;C (Amazon ElastiCache for Memcached가 포함된 Amazon Aurora):&lt;/b&gt; Aurora는 여전히 관계형 데이터베이스로, ElastiCache를 사용하더라도 마이크로초 단위 대기 시간을 일관되게 제공하기 어렵습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;D (Amazon ElastiCache for Memcached가 포함된 Amazon Neptune):&lt;/b&gt; Neptune은 그래프 데이터베이스로, 키-값 데이터베이스에 최적화되어 있지 않으며, ElastiCache를 사용하더라도 요구하는 대기 시간을 보장하기 어렵습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DynamoDB와 DAX의 조합은 키-값 모델을 지원하고 마이크로초 단위의 대기 시간을 제공하므로, 이 시나리오에 가장 적합한 솔루션입니다.&lt;/p&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>aws</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/230</guid>
      <comments>https://hmk1022.tistory.com/entry/AWS-Certified-Solutions-Architect-AssociateSAA-%EC%98%A4%EB%8B%B5-%EB%B0%8F-%ED%95%B4%EC%84%A4-2024-09-08#entry230comment</comments>
      <pubDate>Sun, 8 Sep 2024 15:43:12 +0900</pubDate>
    </item>
    <item>
      <title>공유기의 동작원리</title>
      <link>https://hmk1022.tistory.com/entry/%EA%B3%B5%EC%9C%A0%EA%B8%B0%EC%9D%98-%EB%8F%99%EC%9E%91%EC%9B%90%EB%A6%AC</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;공유기(Router)란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일 IP에서 하위 클라이언트 PC가 유선 또는 무선으로 &lt;b&gt;하나의 인터넷 라인을 공유하여&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;동시에 인터넷 접속이 가능하도록 하는기기&lt;/b&gt;다. WAN과 LAN 사이의 중계 역할을 하며&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공인 IP를 각각의 PC에 사설 IP로 나누어 주고, 공유기에 연결된 장치들이 통신을 시도하면 NAT 기술을 이용하여 외부방 서버에 메세지를전달한다.&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;1280&quot; data-origin-height=&quot;765&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dKF7TA/btsHSEUGjIe/TLp8hrkRucKVoW805NyuB0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dKF7TA/btsHSEUGjIe/TLp8hrkRucKVoW805NyuB0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dKF7TA/btsHSEUGjIe/TLp8hrkRucKVoW805NyuB0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdKF7TA%2FbtsHSEUGjIe%2FTLp8hrkRucKVoW805NyuB0%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;1280&quot; height=&quot;765&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;765&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;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;네트워크 주소 변환(Network Address Translation, NAT) :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;공인 IP와 사설 IP간 주소를 변환시켜주는 기술&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;광대역 통신망(Wide Area Network, WAN) :&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;ISP가 제공하는 서비스에 의해 구축된 네트워크&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;근거리 통신망(Local Area Network, LAN) :&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;작은 지역에서 여러 통신 기기와 상호 연결이 가능하게 하는 네트워크&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;공인 IP(Public IP) :&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;인터넷 사용자의 로컬 네트워크 식별을 위해 ISP가 제공하는 IP&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;사설 IP(Private IP) :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;일반 가정이나 회사에서 사용할 목적으로 할당된 IP&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;3.-공유기-동작-원리&quot; style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 공유기 동작 원리&lt;/b&gt;&lt;/h2&gt;
&lt;h3 id=&quot;3.1.-사설-ip-할당&quot; style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&amp;nbsp;3.1. 사설 IP 할당&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;ISP가 제공하는 WAN 케이블이 공유기의 인터넷이라고 적혀있는 포트에 연결된다. 해당 케이블을 통해 공유기는 자신의 공인 IP 주소를 받는다. 그리고 공유기와 PC 간 LAN 케이블이 LAN 1, 2, 3, 4라고 적혀있는 포트에 연결된다. 이후 공유기는 DHCP를 통해 연결된 PC에 사설 IP를 할당한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;799&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9fnYy/btsHQ9BRyon/rqc0pbnEyPxJbshSgh1wm0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9fnYy/btsHQ9BRyon/rqc0pbnEyPxJbshSgh1wm0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9fnYy/btsHQ9BRyon/rqc0pbnEyPxJbshSgh1wm0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9fnYy%2FbtsHQ9BRyon%2Frqc0pbnEyPxJbshSgh1wm0%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;1200&quot; height=&quot;799&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;799&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;인터넷 서비스 제공자(Internet Service Provider, ISP) :&lt;/b&gt;&lt;/b&gt;&lt;span&gt;인터넷에 접속하는 수단을 제공하는 주체&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;＊ DHCP(Dynamic Host Configuration Protocol) :&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;하위 단말기에 네트워크 정보를 자동으로 할당해주는 프로토콜&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;3.2.-통신&quot; style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.2. 통신&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래 순서에 따라 통신이 진행된다. 순서 2, 3번에 해당하는 내용이 NAT 기술에 해당한다. 인터넷 접속은 공인 IP를 활용해야만 가능하기 때문에 사설 IP를 공인 IP로 바꿔주는 과정이 필요하다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;405&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wgmxu/btsHQ8XeKP4/H614cRj0iP09ldrXODvigk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wgmxu/btsHQ8XeKP4/H614cRj0iP09ldrXODvigk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wgmxu/btsHQ8XeKP4/H614cRj0iP09ldrXODvigk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwgmxu%2FbtsHQ8XeKP4%2FH614cRj0iP09ldrXODvigk%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;1280&quot; height=&quot;405&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;405&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;3.2.-통신&quot; style=&quot;color: #000000; text-align: start;&quot; 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;&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;b&gt;Wi-Fi 표준&lt;/b&gt;: 최신 Wi-Fi 표준일수록 더 빠른 속도와 안정성을 제공합니다. 예를 들어, Wi-Fi 6 (802.11ax)는 이전 표준인 Wi-Fi 5 (802.11ac)보다 속도가 빠르고 더 많은 기기를 효율적으로 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;듀얼 밴드 및 트라이 밴드&lt;/b&gt;: 듀얼 밴드 공유기는 2.4GHz와 5GHz 두 개의 주파수를 제공하며, 트라이 밴드 공유기는 추가적인 5GHz 대역을 제공합니다. 이는 많은 기기를 동시에 연결할 때 성능을 향상시킵니다.&lt;/li&gt;
&lt;/ul&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;b&gt;안테나 수&lt;/b&gt;: 더 많은 안테나를 가진 공유기는 더 넓은 범위와 더 강력한 신호를 제공합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MU-MIMO (Multi-User, Multiple Input, Multiple Output)&lt;/b&gt;: 여러 기기가 동시에 데이터를 송수신할 수 있어 여러 사용자가 있을 때 성능이 향상됩니다.&lt;/li&gt;
&lt;/ul&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;더 강력한 CPU와 더 많은 RAM을 가진 공유기는 더 많은 기기와 더 높은 데이터를 처리하는 데 유리합니다.&lt;/li&gt;
&lt;li&gt;웹 브라우징, 스트리밍 게임 등 많은 데이터 들을 효율적으로 처리하기 위함&lt;/li&gt;
&lt;li&gt;패킷 라우팅, 네트워크 주소 변환(NAT), 방화벽 검사 등 다양한 작업을 빠르게 수행&lt;/li&gt;
&lt;li&gt;여러 개의 클라이언트가 있을때 멀티 태스킹을 원활하게 할수 있게함&lt;/li&gt;
&lt;/ul&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;b&gt;펌웨어 업데이트&lt;/b&gt;: 최신 보안 패치를 제공하는 공유기는 안전하게 네트워크를 유지할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;고급 보안 기능&lt;/b&gt;: 방화벽, VPN 지원, 부모 통제, 게스트 네트워크 등 다양한 보안 및 관리 기능을 제공합니다.&lt;/li&gt;
&lt;/ul&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;b&gt;USB 포트&lt;/b&gt;: 외장 하드 드라이브나 프린터를 네트워크에 쉽게 연결할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;QoS (Quality of Service)&lt;/b&gt;: 네트워크 트래픽을 우선순위에 따라 관리하여 중요한 작업에 대역폭을 할당할 수 있습니다.&lt;/li&gt;
&lt;/ul&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;b&gt;브랜드&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;신뢰도&lt;/b&gt;&lt;span&gt;: &lt;/span&gt;명성&lt;span&gt; &lt;/span&gt;있는&lt;span&gt; &lt;/span&gt;브랜드는&lt;span&gt; &lt;/span&gt;일반적으로&lt;span&gt; &lt;/span&gt;더&lt;span&gt; &lt;/span&gt;높은&lt;span&gt; &lt;/span&gt;가격을&lt;span&gt; &lt;/span&gt;요구하지만&lt;span&gt;, &lt;/span&gt;그만큼&lt;span&gt; &lt;/span&gt;품질과&lt;span&gt; &lt;/span&gt;고객&lt;span&gt; &lt;/span&gt;지원이&lt;span&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>cs</category>
      <category>I</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/229</guid>
      <comments>https://hmk1022.tistory.com/entry/%EA%B3%B5%EC%9C%A0%EA%B8%B0%EC%9D%98-%EB%8F%99%EC%9E%91%EC%9B%90%EB%A6%AC#entry229comment</comments>
      <pubDate>Sat, 8 Jun 2024 20:50:19 +0900</pubDate>
    </item>
    <item>
      <title>기본 경제용어 정리</title>
      <link>https://hmk1022.tistory.com/entry/%EA%B8%B0%EB%B3%B8-%EA%B2%BD%EC%A0%9C%EC%9A%A9%EC%96%B4-%EC%A0%95%EB%A6%AC</link>
      <description>&lt;div&gt;
&lt;div data-scroll-anchor=&quot;true&quot; data-testid=&quot;conversation-turn-3&quot;&gt;
&lt;div data-message-id=&quot;baf32a94-4bd1-4ed2-9b10-61782467dddd&quot; data-message-author-role=&quot;assistant&quot;&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;가산금리 (Spread)&lt;/b&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;예: 은행에서 대출을 받을 때 기준 금리 3%에 가산금리 1%가 더해져 총 4%의 금리를 적용받음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;경기동향지수 (Business Cycle Indicator)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;경상수지 (Current Account Balance)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;고용률 (Employment Rate)&lt;/b&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;예: 100명 중 60명이 일하고 있으면 고용률은 60%.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;고정금리 (Fixed Interest Rate)&lt;/b&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;예: 5년간 고정금리 3%로 대출 받음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;고통지수 (Misery Index)&lt;/b&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;예: 실업률 5% + 물가 상승률 3% = 고통지수 8%.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;골디락스경제 (Goldilocks Economy)&lt;/b&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;예: 경제 성장률 2&lt;s&gt;3%, 물가 상승률 1&lt;/s&gt;2% 수준의 안정적 경제.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공공재 (Public Goods)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;공급탄력성 (Price Elasticity of Supply)&lt;/b&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;예: 가격이 10% 오를 때 공급량이 20% 늘면 공급탄력성이 큼.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공매도 (Short Selling)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;국가신용등급 (Sovereign Credit Rating)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;국채 (Government Bond)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;금본위제 (Gold Standard)&lt;/b&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;예: 금 1온스가 100달러라면 100달러 지폐는 1온스의 금으로 교환 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;금산분리 (Separation of Banking and Commerce)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;기업공개 (IPO, Initial Public Offering)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;기준금리 (Base Rate)&lt;/b&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;예: 한국은행이 기준금리를 2%로 설정하면 다른 은행들도 이를 참고하여 대출 금리 설정.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;기축통화 (Key Currency)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;기회비용 (Opportunity Cost)&lt;/b&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;예: A를 선택하면 B를 포기해야 하는데, B의 가치가 기회비용.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;낙수효과 (Trickle-Down Effect)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;단기금융시장 (Money Market)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;대외의존도 (Degree of External Dependence)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;대체재 (Substitute Goods)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;더블딥 (Double Dip)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;디커플링 (Decoupling)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;디플레이션 (Deflation)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;레버리지 효과 (Leverage Effect)&lt;/b&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;예: 100만원을 빌려서 10% 수익을 내면 자기자본 수익률이 상승함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;만기수익률 (Yield to Maturity, YTM)&lt;/b&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;예: 만기 10년 채권의 만기수익률이 5%라면, 만기까지 연 5%의 수익을 기대할 수 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;마이크로 크레디트 (Microcredit)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;매몰비용 (Sunk Cost)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;명목금리 (Nominal Interest Rate)&lt;/b&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;예: 명목금리 5%일 때 실질 금리는 물가 상승률을 제외한 값.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;무디스 (Moody's)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;물가지수 (Price Index)&lt;/b&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;예: 소비자 물가지수가 2% 상승하면 물가가 2% 오른 것.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;뮤추얼펀드 (Mutual Fund)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;뱅크런 (Bank Run)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;베블런효과 (Veblen Effect)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;변동금리 (Floating Interest Rate)&lt;/b&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;예: 3개월마다 한 번씩 금리가 조정되는 대출.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보호무역주의 (Protectionism)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;본원통화 (Base Money)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;부가가치 (Value Added)&lt;/b&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;예: 원재료 100만원을 가공해 200만원의 제품을 만들면 부가가치 100만원.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;부채담보부증권 (Collateralized Debt Obligation, CDO)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;부채비율 (Debt Ratio)&lt;/b&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;예: 자산 100억원에 부채 50억원이면 부채비율은 50%.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;분수효과 (Fountain Effect)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;빅맥지수 (Big Mac Index)&lt;/b&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;예: 한국에서 빅맥이 4천원, 미국에서 5달러면 환율을 비교 가능.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;상장지수펀드 (ETF, Exchange-Traded Fund)&lt;/b&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;예: 코스피200 지수를 추종하는 ETF에 투자하면 코스피200과 비슷한 수익을 기대.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서킷브레이커 (Circuit Breaker)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;선물거래 (Futures Trading)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;소득주도성장 (Income-Led Growth)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;수요탄력성 (Price Elasticity of Demand)&lt;/b&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;예: 가격이 10% 오를 때 수요량이 20% 줄면 수요탄력성이 큼.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;스왑 (Swap)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;스톡옵션 (Stock Option)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;시뇨리지 (Seigniorage)&lt;/b&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;예: 1만원짜리 지폐를 500원에 만들어 발행하면 9500원의 이익.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;신용경색 (Credit Crunch)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;신주인수권부사채 (Bond with Warrant, BW)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;실질임금 (Real Wage)&lt;/b&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;예: 명목임금 100만원이지만 물가가 오르면 실질임금은 줄어듦.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;애그플레이션 (Agflation)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;양도성예금증서 (CD, Certificate of Deposit)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;양적완화정책 (Quantitative Easing, QE)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;어음관리계좌 (CMA, Cash Management Account)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;연방준비제도 (FRS)/연방준비은행 (FRB) (Federal Reserve System/Bank)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;엥겔의 법칙 (Engel's Law)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;역모기지론 (Reverse Mortgage)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;예대율 (Loan-to-Deposit Ratio)&lt;/b&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;예: 예금이 100억원이고 대출이 80억원이면 예대율은 80%.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;옵션 (Option)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;외환보유액 (Foreign Exchange Reserves)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;워크아웃 (Workout)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;원금리스크 (Principal Risk)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;유동성 (Liquidity)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;이중통화채 (Dual Currency Bond)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;자기자본비율 (Equity Ratio)&lt;/b&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;예: 자본 100억원 중 자기자본이 60억원이면 자기자본비율은 60%.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자발적 실업 (Voluntary Unemployment)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;장단기금리차 (Yield Curve Spread)&lt;/b&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;예: 10년 만기 국채 금리가 5%, 1년 만기 국채 금리가 3%면 장단기금리차는 2%.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;장외시장 (Over-The-Counter, OTC)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;전환사채 (Convertible Bond)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;정크본드 (Junk Bond)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;제로금리정책 (Zero Interest Rate Policy)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중앙은행이 금리를 0%에 가깝게 유지하는 정책.&lt;/li&gt;
&lt;li&gt;예: 경기 부양을 위해 기준금리를 0%로 설정.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주가수익률 (PER, Price Earnings Ratio)&lt;/b&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;예: 주가가 10만원, 주당순이익이 1만원이면 PER은 10.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주가지수 (Stock Index)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;조세부담률 (Tax Burden Ratio)&lt;/b&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;예: 소득 100만원 중 세금이 20만원이면 조세부담률은 20%.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주당순이익 (EPS, Earnings Per Share)&lt;/b&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;예: 순이익이 1억원, 발행 주식이 10만주면 EPS는 1천원.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;중앙은행 (Central Bank)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;증거금 (Margin)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;지주회사 (Holding Company)&lt;/b&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;예: A회사가 B회사의 주식 50% 이상을 소유해 지배함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;추심 (Collection)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;치킨게임 (Chicken Game)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;카르텔 (Cartel)&lt;/b&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;예: OPEC 국가들이 석유 생산량을 조절해 가격을 통제.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;콜옵션 (Call Option)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;통화스왑 (Currency Swap)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;투자은행 (Investment Bank)&lt;/b&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;예: 골드만삭스, JP모건.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;특수목적기구 (SPV, Special Purpose Vehicle)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;파생금융상품 (Derivatives)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;평가절하 (Devaluation)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;표면금리 (Coupon Rate)&lt;/b&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;예: 5% 표면금리를 가진 채권은 매년 5%의 이자를 지급.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;한계비용 (Marginal Cost)&lt;/b&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;예: 100개를 생산할 때 1개 추가 생산 비용이 5천원.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;헤지펀드 (Hedge Fund)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;환율조작국 (Currency Manipulator)&lt;/b&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;/li&gt;
&lt;li&gt;&lt;b&gt;M&amp;amp;A (Mergers and Acquisitions)&lt;/b&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;예: A회사가 B회사를 인수해 합병함.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;매출채권회전율&lt;br /&gt;&lt;/b&gt;특정기간동안 매출채권이 얼마나 현금화 됐는지&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;, &lt;/span&gt;회전일수는 외상값을 받는데 얼마나 걸렸는지 확인하는 지표다&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;.&lt;br /&gt;&lt;/span&gt;매출채권회전이 중요한이유는 기업이 빠른시간안에 유동성을 확보해야 향후경영에 사용할 수 있기때문&lt;br /&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&amp;nbsp;재고자산회전율&lt;br /&gt;&lt;/b&gt;매출액을 재고자산으로 나눈 비율, 재고자산이 얼마나 빨리 팔려나가는지를 보여주는 지표&lt;br /&gt;짧으면 짧을 수록 좋다고 볼 수 있음 =&amp;gt; 재고 관리가 효율적으로 이루어지고 있음&lt;b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;div data-testid=&quot;conversation-turn-3&quot; data-scroll-anchor=&quot;true&quot;&gt;
&lt;div data-message-author-role=&quot;assistant&quot; data-message-id=&quot;baf32a94-4bd1-4ed2-9b10-61782467dddd&quot;&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;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;</description>
      <category>경제</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/228</guid>
      <comments>https://hmk1022.tistory.com/entry/%EA%B8%B0%EB%B3%B8-%EA%B2%BD%EC%A0%9C%EC%9A%A9%EC%96%B4-%EC%A0%95%EB%A6%AC#entry228comment</comments>
      <pubDate>Thu, 30 May 2024 21:47:39 +0900</pubDate>
    </item>
    <item>
      <title>프론트엔드 코딩 컨벤션 리마인드</title>
      <link>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%BD%94%EB%94%A9-%EC%BB%A8%EB%B2%A4%EC%85%98-%EB%A6%AC%EB%A7%88%EC%9D%B8%EB%93%9C</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;/p&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-origin-width=&quot;458&quot; data-origin-height=&quot;354&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bSVYjs/btsHzwa257A/SGetNToy6HHpqpBS2yx8U1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bSVYjs/btsHzwa257A/SGetNToy6HHpqpBS2yx8U1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bSVYjs/btsHzwa257A/SGetNToy6HHpqpBS2yx8U1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSVYjs%2FbtsHzwa257A%2FSGetNToy6HHpqpBS2yx8U1%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;458&quot; height=&quot;354&quot; data-origin-width=&quot;458&quot; data-origin-height=&quot;354&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;props로 setter(setState)하는 콜백은 되도록이면 넘기지 말기&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;- 되도록이면 호출이 필요한 시점에 호출을 트리거하는 곳에서 호출하자&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;708&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LYerw/btsHxtHmQi9/VoUbA2PS1YuQgaowsCNU0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LYerw/btsHxtHmQi9/VoUbA2PS1YuQgaowsCNU0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LYerw/btsHxtHmQi9/VoUbA2PS1YuQgaowsCNU0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLYerw%2FbtsHxtHmQi9%2FVoUbA2PS1YuQgaowsCNU0k%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;726&quot; height=&quot;586&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;708&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;style7&quot; /&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- props 이름 = on + 이벤트 이름&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- props에 적용하는 핸들러 이름 = handle + 이벤트 이름&lt;/p&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;onSelect도 onChange로 바뀌고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;updateOptionNameEditMode도 onChangeOptionNameEditMode로 바뀌어야 한다.&lt;/p&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: #9d9d9d;&quot;&gt;(updateOptionNameEditMode은 boolean값을 받아 editMode를 set 하는 역할을 하기 때문)&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;879&quot; data-origin-height=&quot;276&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rzrRR/btsHzasw7Kf/WNe6XeCF81MqFPkmTyScu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rzrRR/btsHzasw7Kf/WNe6XeCF81MqFPkmTyScu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rzrRR/btsHzasw7Kf/WNe6XeCF81MqFPkmTyScu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrzrRR%2FbtsHzasw7Kf%2FWNe6XeCF81MqFPkmTyScu1%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;755&quot; height=&quot;237&quot; data-origin-width=&quot;879&quot; data-origin-height=&quot;276&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;style7&quot; /&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;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 아래 eslint-plugin으로 싸악 청소해 주자 (게비스콘 짤)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.npmjs.com/package/eslint-plugin-unused-imports?activeTab=dependencies&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.npmjs.com/package/eslint-plugin-unused-imports?activeTab=dependencies&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;454&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bEckq8/btsHyvKZjgK/BND0ktevA9c2VK4L9xrya0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bEckq8/btsHyvKZjgK/BND0ktevA9c2VK4L9xrya0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bEckq8/btsHyvKZjgK/BND0ktevA9c2VK4L9xrya0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbEckq8%2FbtsHyvKZjgK%2FBND0ktevA9c2VK4L9xrya0%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;880&quot; height=&quot;454&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;454&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;br /&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;누가 봐도 거슬리는 스타일은 FE 개발자 선에서 처리해 보자&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;881&quot; data-origin-height=&quot;201&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYDCji/btsHzbrrTta/UxV5si9m6H78KuC2VFh1xK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYDCji/btsHzbrrTta/UxV5si9m6H78KuC2VFh1xK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYDCji/btsHzbrrTta/UxV5si9m6H78KuC2VFh1xK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYDCji%2FbtsHzbrrTta%2FUxV5si9m6H78KuC2VFh1xK%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;881&quot; height=&quot;201&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;201&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 예상할 수 있는 에러는 명시적으로 Error 객체를 던져주자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- sentry &amp;amp; catch에서 에러를 잡아낼 수 있음&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;878&quot; data-origin-height=&quot;335&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xbm2w/btsHzc4XvJS/9iWF6BOzkw6KQKI3PpNPK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xbm2w/btsHzc4XvJS/9iWF6BOzkw6KQKI3PpNPK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xbm2w/btsHzc4XvJS/9iWF6BOzkw6KQKI3PpNPK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxbm2w%2FbtsHzc4XvJS%2F9iWF6BOzkw6KQKI3PpNPK1%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;878&quot; height=&quot;335&quot; data-origin-width=&quot;878&quot; data-origin-height=&quot;335&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- else 대신 예상할 수 있는 에러는 명시적으로 Error 객체를 던져주자&lt;br /&gt;- 유지보수가 더 용이하며 코드를 보고 의도를 파악하기 더 쉬워진다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;299&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NqJ9x/btsHxJCVTJe/xUj75yWd7TtGhaIteP9L00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NqJ9x/btsHxJCVTJe/xUj75yWd7TtGhaIteP9L00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NqJ9x/btsHxJCVTJe/xUj75yWd7TtGhaIteP9L00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNqJ9x%2FbtsHxJCVTJe%2FxUj75yWd7TtGhaIteP9L00%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;876&quot; height=&quot;299&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;299&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;b&gt;코드예시&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1716386220211&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const fetchRecommendOptionNames = useCallback(
    (sellingMarket: SellingMarket) =&amp;gt; {
      switch (sellingMarket) {
        case SellingMarket.Coupang:
          fetchCoupangRecommendOptionName();
          break;
        case SellingMarket.St11:
        case SellingMarket.Auction:
          fetchEsmRecommendOptionName();
          break;
        default:
          throw new Error(
            `fetchRecommendOptionNames: ${sellingMarket} sellingMarket is invalid`,
          );
      }
    },
    [fetchCoupangRecommendOptionName, fetchEsmRecommendOptionName],
);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;이벤트  props 네이밍 컨벤션&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;- 네이티브 이벤트 핸들러 기반으로 보편적인 네이밍&lt;/p&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;879&quot; data-origin-height=&quot;252&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkwG4s/btsHyQH4MZ9/2zLSxLF657xM6ptKUfEsH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkwG4s/btsHyQH4MZ9/2zLSxLF657xM6ptKUfEsH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkwG4s/btsHyQH4MZ9/2zLSxLF657xM6ptKUfEsH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkwG4s%2FbtsHyQH4MZ9%2F2zLSxLF657xM6ptKUfEsH0%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;879&quot; height=&quot;252&quot; data-origin-width=&quot;879&quot; data-origin-height=&quot;252&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;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 써보니 좀만 신경 썼다면 좋았던 경우가 대부분 인 것 같다..&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;명심하자 신경쓰지 않고 대충 짠 코드는&lt;br /&gt;&lt;br /&gt;동료의 코드리뷰 리소스 + 나의 재수정 리소스&lt;br /&gt;더 나아가 조직 전체의 리소스 저하로 초래된다 정신 차리고 차분하게 생각하고 더 신경 쓰자&lt;/blockquote&gt;</description>
      <category>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/227</guid>
      <comments>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EC%BD%94%EB%94%A9-%EC%BB%A8%EB%B2%A4%EC%85%98-%EB%A6%AC%EB%A7%88%EC%9D%B8%EB%93%9C#entry227comment</comments>
      <pubDate>Wed, 22 May 2024 23:03:56 +0900</pubDate>
    </item>
    <item>
      <title>emotion(css-in-js)과 nextjs</title>
      <link>https://hmk1022.tistory.com/entry/emotioncss-in-js%EA%B3%BC-nextjs</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;nextjs와 emotion(css-in-js)을 같이 사용하다.&lt;br /&gt;두 개의 조합이 별로 좋지 못하다는 생각이 들어 emotion을 사용해 왔던 이유와&lt;br /&gt;조합이 좋지 못한 nextjs와 계속 같이 사용을 하는 게 맞을지에 대한 판단을 하기 위해 정리해보려고 합니다.&lt;br /&gt;&lt;br /&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/yBIHB/btsHbkKkoBj/EWkBikKTgrEtSHb3KveRkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yBIHB/btsHbkKkoBj/EWkBikKTgrEtSHb3KveRkK/img.png&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;959&quot; data-is-animation=&quot;false&quot; width=&quot;475&quot; height=&quot;356&quot; style=&quot;width: 39.5596%; margin-right: 10px;&quot; data-widthpercent=&quot;40.03&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yBIHB/btsHbkKkoBj/EWkBikKTgrEtSHb3KveRkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyBIHB%2FbtsHbkKkoBj%2FEWkBikKTgrEtSHb3KveRkK%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;1280&quot; height=&quot;959&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIZ8Rs/btsHedW2ebk/6kH7HmL2lt94BR8tiL1Rc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIZ8Rs/btsHedW2ebk/6kH7HmL2lt94BR8tiL1Rc0/img.png&quot; data-origin-width=&quot;520&quot; data-origin-height=&quot;260&quot; data-is-animation=&quot;false&quot; style=&quot;width: 59.2776%;&quot; data-widthpercent=&quot;59.97&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIZ8Rs/btsHedW2ebk/6kH7HmL2lt94BR8tiL1Rc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIZ8Rs%2FbtsHedW2ebk%2F6kH7HmL2lt94BR8tiL1Rc0%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;520&quot; height=&quot;260&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;emotion/css-in-js 방식의 장단점&lt;/h3&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;br /&gt;&lt;b&gt;가독성&lt;/b&gt; &lt;br /&gt;- css 혹은 id 같은 선택자로 css를 작성하지 않고 태그명 자체를 개별로 명시해서 사용할 수 있음&lt;br /&gt;&lt;br /&gt;&lt;b&gt;스타일 충돌 방지&lt;/b&gt; &lt;br /&gt;- emotion을 이용한 스타일링은 개발자가 임의로 선택자를 지정해 작성한 css와 달리 개별 스코프를 가지며 css 충돌 가능성이 매우 낮음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;b&gt;상태에 따른 스타일 변경용이&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- &lt;/span&gt;emotion 태그 내에 js코드를 혼합해서 작성이 가능해 react의 state에 따른 스타일 구현하기가 비교적 편함&lt;/p&gt;
&lt;pre id=&quot;code_1714907239677&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export const Description: React.FC&amp;lt;IProps&amp;gt; = ({
  label,
  labelWidth,
  content,
}) =&amp;gt; {
  return (
    &amp;lt;Wrapper&amp;gt;
      &amp;lt;LabelArea width={labelWidth}&amp;gt;{label}&amp;lt;/LabelArea&amp;gt;
      &amp;lt;ContentArea&amp;gt;{content}&amp;lt;/ContentArea&amp;gt;
    &amp;lt;/Wrapper&amp;gt;
  );
};

/** emotion styled */
export const Wrapper = styled.section`
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  width: 100%;
  border-top: 1px solid ${COLOR.SKELETON.TEXT_03};
  border-bottom: 1px solid ${COLOR.SKELETON.TEXT_03};
  border-right: 1px solid ${COLOR.SKELETON.TEXT_03};
  margin-bottom: -1px;
`;

export const LabelArea = styled.span&amp;lt;{ width?: string }&amp;gt;`
  display: flex;
  width: ${(props) =&amp;gt; props.width ?? '12rem'};
  padding: 0.75rem 1.5rem;
  align-items: center;
  gap: 0.5rem;
  align-self: stretch;
  background: ${COLOR.UI_UP_02};
  color: ${COLOR.TEXT_D_02};
  border-left: 1px solid ${COLOR.UI_UP_UI_STROKE};
  border-right: 1px solid ${COLOR.UI_UP_UI_STROKE};

  ${BODY_BODY_LONG_2}
`;

export const ContentArea = styled.span`
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0 0.75rem;

  color: ${COLOR.TEXT_D_01};
  ${BODY_BODY_LONG_2}

  input {
    padding-left: 0;
    max-width: 7rem;
  }
`;&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;br /&gt;&lt;b&gt;nextjs와 조합&lt;/b&gt; &lt;br /&gt;- RSC(서버컴포넌트), SSR과 같은 방식에서 지원이 미흡하거나 아예 사용자체가 불가&lt;br /&gt;아래 이슈들이 모두 해결되어야 사용가능하지 않을까 싶음&lt;br /&gt;&lt;a href=&quot;https://github.com/emotion-js/emotion/issues/2928&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/emotion-js/emotion/issues/2928&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;성능&lt;/b&gt; &lt;br /&gt;- css-in-js 방식은 컴포넌트가 렌더링 될 때 css 스타일을 따로 직렬화하는 과정이 필요함 &amp;amp; js 번들크기 증가&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;정량적인 성능 측정은 아래 글을 참고하면 좋을 것 같다.&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;a href=&quot;https://www.samsungsds.com/kr/insights/web_component.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.samsungsds.com/kr/insights/web_component.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1714907970944&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;웹 컴포넌트 스타일링 관리 CSS-in-JS vs CSS-in-CSS | 인사이트리포트 | 삼성SDS&quot; data-og-description=&quot;HTML(Hypertext Markup Language)이 처음 등장한 1991년에는 CSS(Cascading Style Sheets)가 없었습니다. 웹 이용자들이 늘어나면서 디자인에 대한 요구가 커졌고 웹 고안자들은 HTML을 꾸며주는 언어의 필요성을 &quot; data-og-host=&quot;www.samsungsds.com&quot; data-og-source-url=&quot;https://www.samsungsds.com/kr/insights/web_component.html&quot; data-og-url=&quot;https://www.samsungsds.com/kr/insights/web_component.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/6yFe9/hyVZqhsIcr/FWGDc9sZLx4tKqncfo7Qd0/img.jpg?width=900&amp;amp;height=600&amp;amp;face=0_0_900_600,https://scrap.kakaocdn.net/dn/bEfQMo/hyVZnyhTmM/gJIA4Xc4VadvH6Q4QvET0k/img.jpg?width=844&amp;amp;height=359&amp;amp;face=0_0_844_359,https://scrap.kakaocdn.net/dn/V2y57/hyVZjbARfZ/DKV9gLQc1NsRz9iUrLJuHK/img.jpg?width=844&amp;amp;height=331&amp;amp;face=0_0_844_331&quot;&gt;&lt;a href=&quot;https://www.samsungsds.com/kr/insights/web_component.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.samsungsds.com/kr/insights/web_component.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/6yFe9/hyVZqhsIcr/FWGDc9sZLx4tKqncfo7Qd0/img.jpg?width=900&amp;amp;height=600&amp;amp;face=0_0_900_600,https://scrap.kakaocdn.net/dn/bEfQMo/hyVZnyhTmM/gJIA4Xc4VadvH6Q4QvET0k/img.jpg?width=844&amp;amp;height=359&amp;amp;face=0_0_844_359,https://scrap.kakaocdn.net/dn/V2y57/hyVZjbARfZ/DKV9gLQc1NsRz9iUrLJuHK/img.jpg?width=844&amp;amp;height=331&amp;amp;face=0_0_844_331');&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;웹 컴포넌트 스타일링 관리 CSS-in-JS vs CSS-in-CSS | 인사이트리포트 | 삼성SDS&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;HTML(Hypertext Markup Language)이 처음 등장한 1991년에는 CSS(Cascading Style Sheets)가 없었습니다. 웹 이용자들이 늘어나면서 디자인에 대한 요구가 커졌고 웹 고안자들은 HTML을 꾸며주는 언어의 필요성을&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.samsungsds.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;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;결론&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;나열해 보니 &lt;b&gt;DX vs 성능/nextjs와 조합 측면&lt;/b&gt;에서 선택을 해야 할 것 같긴 하다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확실히 개발경험은 emotion 쪽이 더 가독성 좋고 명시적인 스타일링이 가능했었던 것 같아서 만족하며 쓰는 중이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 상황에선 nextjs&lt;span&gt;에서&lt;/span&gt; emotion &lt;span&gt;관련된&lt;/span&gt; &lt;span&gt;이슈를&lt;/span&gt; &lt;span&gt;빨리 해결해 주면 best이긴 하나...&lt;/span&gt; 몇 년째 개선의 여지가 안 보인다...&lt;br /&gt;&lt;br /&gt;결론은 성능상 이점이 있는, 그리고 표준에 맞는 css-in-css 방식을 사용해 nextjs에서 제공하는 기능(SSR, SSG, ISR, RSC)등을 이용하는 쪽으로 개발할 예정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 더해 next 측에서도 스타일링 방법으로 PostCss나 Tailwind CSS를 사용하는 것을 권장하고 있다.&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;a href=&quot;https://nextjs.org/docs/app/building-your-application/styling/css-in-js#:~:text=we%20recommend%20using%20CSS%20Modules%20or%20other%20solutions%20that%20output%20CSS%20files%2C%20like%20PostCSS%20or%20Tailwind%20CSS.&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://nextjs.org/docs/app/building-your-application/styling/css-in-js#:~:text=we%20recommend%20using%20CSS%20Modules%20or%20other%20solutions%20that%20output%20CSS%20files%2C%20like%20PostCSS%20or%20Tailwind%20CSS.&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/226</guid>
      <comments>https://hmk1022.tistory.com/entry/emotioncss-in-js%EA%B3%BC-nextjs#entry226comment</comments>
      <pubDate>Sun, 5 May 2024 20:19:38 +0900</pubDate>
    </item>
    <item>
      <title>몽고디비란? mongoDB</title>
      <link>https://hmk1022.tistory.com/entry/%EB%AA%BD%EA%B3%A0%EB%94%94%EB%B9%84%EB%9E%80-mongoDB</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;몽고 DB의&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;기본&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;개념&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MongoDB는 고성능, 고가용성 및 쉬운 확장성을 제공하는 NoSQL, Document 지향 데이터베이스입니다.&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터를 배열 및 중첩 Document와 같은 복잡한 데이터 유형을 효율적으로 저장할 수 있는 유연한 JSON과 유사한 형식인 &lt;b&gt;BSON(Binary JSON)&lt;/b&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;JSON &amp;lt;=&amp;gt; BSON 직렬화, 역직렬화 과정에서 CPU 리소스가 많이 사용될 수 있으나,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;이를 내부 최적화 알고리즘으로 개선했고, &lt;br /&gt;텍스트 보다 적은 용량을 사용해 저장공간의 용이성도 가져온다.&lt;br /&gt;일반적으로 데이터베이스 I/O 연산이 더 큰 병목 현상을 일으키 때문에&amp;nbsp;&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;113&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bi4fZy/btsGNFV0xz0/3wQTs3I7xMXeF3WTQWMfeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bi4fZy/btsGNFV0xz0/3wQTs3I7xMXeF3WTQWMfeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bi4fZy/btsGNFV0xz0/3wQTs3I7xMXeF3WTQWMfeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbi4fZy%2FbtsGNFV0xz0%2F3wQTs3I7xMXeF3WTQWMfeK%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;137&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;113&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;style7&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;몽고 DB의&lt;/b&gt;&lt;b&gt; 유연과 확장&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몽고 DB의 장점을 두 개의 키워드로 뽑으면 유연과 확장이라고 말할 수 있을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같은 특징이 유연과 확장에 용이한 db라고 생각하는 이유이며, 빠르게 변화하는 비즈니스 요구에 유연하게 대응하기에 적합하지 않나 싶다.&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;span&gt;&lt;b&gt;스키마&lt;/b&gt;&lt;/span&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&lt;b&gt;없음&lt;/b&gt;&lt;/span&gt;&lt;b&gt; (Schema-less)&lt;/b&gt;:&lt;br /&gt;&lt;span&gt;MongoDB&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;스키마&lt;span&gt; &lt;/span&gt;없는&lt;span&gt; &lt;/span&gt;데이터베이스로&lt;span&gt;, &lt;/span&gt;데이터의&lt;span&gt; &lt;/span&gt;구조를&lt;span&gt; &lt;/span&gt;미리&lt;span&gt; &lt;/span&gt;정의하지&lt;span&gt; &lt;/span&gt;않아도&lt;span&gt; &lt;/span&gt;됩니다&lt;span&gt;. &lt;/span&gt;이로&lt;span&gt; &lt;/span&gt;인해&lt;span&gt; &lt;/span&gt;애플리케이션의&lt;span&gt; &lt;/span&gt;요구&lt;span&gt; &lt;/span&gt;사항이&lt;span&gt; &lt;/span&gt;변경되거나&lt;span&gt; &lt;/span&gt;다양한&lt;span&gt; &lt;/span&gt;데이터&lt;span&gt; &lt;/span&gt;형식을&lt;span&gt; &lt;/span&gt;저장할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있어&lt;span&gt; &lt;/span&gt;유연성이&lt;span&gt; &lt;/span&gt;높습니다&lt;span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;동적&lt;/b&gt;&lt;/span&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&lt;b&gt;스키마&lt;/b&gt;&lt;/span&gt;&lt;b&gt; (Dynamic Schema)&lt;/b&gt;:&lt;span&gt;&lt;br /&gt;MongoDB&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;동적&lt;span&gt; &lt;/span&gt;스키마를&lt;span&gt; &lt;/span&gt;지원합니다&lt;span&gt;. &lt;/span&gt;이는&lt;span&gt; &lt;/span&gt;컬렉션&lt;span&gt; &lt;/span&gt;내에서&lt;span&gt; &lt;/span&gt;각&lt;span&gt; &lt;/span&gt;문서가&lt;span&gt; &lt;/span&gt;독립적으로&lt;span&gt; &lt;/span&gt;다른&lt;span&gt; &lt;/span&gt;필드를&lt;span&gt; &lt;/span&gt;가질&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있음을&lt;span&gt; &lt;/span&gt;의미합니다&lt;span&gt;. &lt;/span&gt;필요에&lt;span&gt; &lt;/span&gt;따라&lt;span&gt; &lt;/span&gt;필드를&lt;span&gt; &lt;/span&gt;추가하거나&lt;span&gt; &lt;/span&gt;제거할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있어&lt;span&gt;, &lt;/span&gt;데이터&lt;span&gt; &lt;/span&gt;모델의&lt;span&gt; &lt;/span&gt;변화에&lt;span&gt; &lt;/span&gt;쉽게&lt;span&gt; &lt;/span&gt;대응할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;수평적&lt;/b&gt;&lt;/span&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&lt;b&gt;확장&lt;/b&gt;&lt;/span&gt;&lt;b&gt; (Horizontal Scalability)&lt;/b&gt;:&lt;br /&gt;&lt;span&gt;MongoDB&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;쉽게&lt;span&gt; &lt;/span&gt;클러스터를&lt;span&gt; &lt;/span&gt;형성하여&lt;span&gt; &lt;/span&gt;데이터베이스를&lt;span&gt; &lt;/span&gt;확장할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;. &lt;/span&gt;이는&lt;span&gt; &lt;/span&gt;샤딩&lt;span&gt;(sharding) &lt;/span&gt;기능을&lt;span&gt; &lt;/span&gt;통해&lt;span&gt; &lt;/span&gt;데이터를&lt;span&gt; &lt;/span&gt;여러&lt;span&gt; &lt;/span&gt;노드에&lt;span&gt; &lt;/span&gt;분산시키고&lt;span&gt;, &lt;/span&gt;높은&lt;span&gt; &lt;/span&gt;트래픽과&lt;span&gt; &lt;/span&gt;대규모&lt;span&gt; &lt;/span&gt;데이터를&lt;span&gt; &lt;/span&gt;처리할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있게&lt;span&gt; 해줍니다해 줍니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;인덱싱&lt;/b&gt;&lt;/span&gt;&lt;b&gt; (Indexing)&lt;/b&gt;:&lt;br /&gt;&lt;span&gt;MongoDB&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;다양한&lt;span&gt; &lt;/span&gt;인덱싱&lt;span&gt; &lt;/span&gt;옵션을&lt;span&gt; &lt;/span&gt;제공하여&lt;span&gt; &lt;/span&gt;쿼리&lt;span&gt; &lt;/span&gt;성능을&lt;span&gt; &lt;/span&gt;최적화합니다&lt;span&gt;. &lt;/span&gt;필드에&lt;span&gt; &lt;/span&gt;인덱스를&lt;span&gt; &lt;/span&gt;추가하면&lt;span&gt; &lt;/span&gt;데이터&lt;span&gt; &lt;/span&gt;검색과&lt;span&gt; &lt;/span&gt;정렬이&lt;span&gt; &lt;/span&gt;빨라져서&lt;span&gt; &lt;/span&gt;애플리케이션의&lt;span&gt; &lt;/span&gt;응답&lt;span&gt; &lt;/span&gt;시간을&lt;span&gt; &lt;/span&gt;개선할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다양한&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;데이터&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;모델&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;지원&lt;/b&gt;&lt;span&gt;:&lt;br /&gt;&lt;/span&gt;&lt;span&gt;MongoDB&lt;/span&gt;는&lt;span&gt; Document &lt;/span&gt;지향&lt;span&gt; &lt;/span&gt;데이터베이스로서&lt;span&gt;, &lt;/span&gt;배열&lt;span&gt;, &lt;/span&gt;중첩된&lt;span&gt; &lt;/span&gt;문서&lt;span&gt;, &lt;/span&gt;기본&lt;span&gt; &lt;/span&gt;타입&lt;span&gt; &lt;/span&gt;등&lt;span&gt; &lt;/span&gt;다양한&lt;span&gt; &lt;/span&gt;데이터&lt;span&gt; &lt;/span&gt;유형을&lt;span&gt; &lt;/span&gt;지원합니다&lt;span&gt;. &lt;/span&gt;이로&lt;span&gt; &lt;/span&gt;인해&lt;span&gt; &lt;/span&gt;복잡한&lt;span&gt; &lt;/span&gt;데이터&lt;span&gt; &lt;/span&gt;구조를&lt;span&gt; &lt;/span&gt;표현하고&lt;span&gt; 쿼리할 &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;몽고 DB&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: left;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MongoDB를 사용해야 할 때:&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;유연성이 필요한 경우&lt;/b&gt;: 스키마가 자주 변경되거나 복잡한 데이터 구조를 가진 애플리케이션에 적합합니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;빠른 개발과 프로토타이핑&lt;/b&gt;: 데이터 모델을 빠르게 반영하고 수정할 수 있어, 초기 개발 단계에서 빠른 프로토타이핑이 필요한 경우에 적합합니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대규모 데이터와 높은 트래픽&lt;/b&gt;: 수평적 확장이 용이하므로, 대규모 데이터 집합과 높은 트래픽을 처리해야 하는 애플리케이션에 적합합니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;다양한 데이터 모델&lt;/b&gt;: 배열, 중첩된 문서, 기본 타입 등 다양한 데이터 유형을 지원하므로, 복잡한 데이터 구조를 관리해야 하는 경우에 적합합니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;실시간 분석과 집계&lt;/b&gt;: MongoDB는 실시간 집계와 분석을 위한 쿼리 기능을 제공하여 빠른 데이터 분석이 필요한 경우에 적합합니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MongoDB를 사용하면 안 될 때:&lt;/b&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;span&gt;&lt;b&gt;ACID &lt;/b&gt;&lt;/span&gt;&lt;b&gt;트랜잭션&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;필요&lt;/b&gt;&lt;span&gt;: MongoDB&lt;/span&gt;는&lt;span&gt; ACID &lt;/span&gt;트랜잭션을&lt;span&gt; &lt;/span&gt;제한적으로&lt;span&gt; &lt;/span&gt;지원합니다&lt;span&gt;. &lt;/span&gt;복잡한&lt;span&gt; &lt;/span&gt;트랜잭션&lt;span&gt; &lt;/span&gt;처리가&lt;span&gt; &lt;/span&gt;필요한&lt;span&gt; &lt;/span&gt;애플리케이션의&lt;span&gt; &lt;/span&gt;경우&lt;span&gt; &lt;/span&gt;관계형&lt;span&gt; &lt;/span&gt;데이터베이스가&lt;span&gt; &lt;/span&gt;더&lt;span&gt; &lt;/span&gt;적합할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;br /&gt;&lt;br /&gt;mongoDB는 &lt;a href=&quot;https://www.databricks.com/kr/glossary/acid-transactions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;ACID&lt;/a&gt; 가 아닌 &lt;a href=&quot;https://velog.io/@jeb1225/ACIDvsBASE&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;BASE&lt;/a&gt; 기반 트랜잭션을 사용합니다.&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;구조화된 특성을 감안할 때&lt;/span&gt;&lt;br /&gt;- ACID 호환 DB는 일관성, 예측 가능성 및 안정성이 필요한 프로젝트에 적합한 것 같고,&lt;br /&gt;- BASE는 더 쉽게 확장할 수 있고 더 많은 유연성을 제공해주나, BASE 모델의 한계를 알고 다루는 숙련된 개발자가 필요해 보인다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&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;span&gt;&lt;b&gt;속성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;BASE&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&lt;b&gt;ACID&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;적용분야&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;NOSQL&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;RDBMS&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;일관성측면&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;약한&lt;span&gt; &lt;/span&gt;일관성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;강한&lt;span&gt; &lt;/span&gt;일관성&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;중점사항&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;Availability&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;&amp;lsquo;Commit&amp;rsquo;&lt;span&gt;에&lt;/span&gt; &lt;span&gt;집중&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;시스템측면&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;성능에&lt;span&gt; &lt;/span&gt;초점&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;엄격한&lt;span&gt; &lt;/span&gt;데이터관리&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;span&gt;효율성&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;쿼리디자인이&lt;span&gt; &lt;/span&gt;중요&lt;/span&gt;&lt;/td&gt;
&lt;td&gt;&lt;span&gt;테이블&lt;span&gt; &lt;/span&gt;디자인이&lt;span&gt; &lt;/span&gt;중요&lt;/span&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;정교한&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;쿼리&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;최적화&lt;/b&gt;&lt;span&gt;: MongoDB&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;강력한&lt;span&gt; &lt;/span&gt;쿼리&lt;span&gt; &lt;/span&gt;기능을&lt;span&gt; &lt;/span&gt;제공하지만&lt;span&gt;, &lt;/span&gt;관계형&lt;span&gt; &lt;/span&gt;데이터베이스의&lt;span&gt; SQL &lt;/span&gt;쿼리&lt;span&gt; &lt;/span&gt;최적화&lt;span&gt; &lt;/span&gt;능력에는&lt;span&gt; &lt;/span&gt;미치지&lt;span&gt; &lt;/span&gt;못할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;정교한&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;인덱싱&lt;/b&gt;&lt;span&gt;: MongoDB&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;다양한&lt;span&gt; &lt;/span&gt;인덱싱&lt;span&gt; &lt;/span&gt;옵션을&lt;span&gt; &lt;/span&gt;제공하지만&lt;span&gt;, &lt;/span&gt;관계형&lt;span&gt; &lt;/span&gt;데이터베이스의&lt;span&gt; &lt;/span&gt;정교한&lt;span&gt; &lt;/span&gt;인덱싱&lt;span&gt; &lt;/span&gt;기능에&lt;span&gt; &lt;/span&gt;비해&lt;span&gt; &lt;/span&gt;제한적일&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;고정된&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;스키마&lt;/b&gt;&lt;span&gt;: &lt;/span&gt;애플리케이션의&lt;span&gt; &lt;/span&gt;데이터&lt;span&gt; &lt;/span&gt;모델이&lt;span&gt; &lt;/span&gt;고정된&lt;span&gt; &lt;/span&gt;스키마를&lt;span&gt; &lt;/span&gt;필요로&lt;span&gt; &lt;/span&gt;하는&lt;span&gt; &lt;/span&gt;경우&lt;span&gt;, &lt;/span&gt;관계형&lt;span&gt; &lt;/span&gt;데이터베이스가&lt;span&gt; &lt;/span&gt;더&lt;span&gt; &lt;/span&gt;적합할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;엄격한&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;보안&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;요구&lt;/b&gt;&lt;span&gt;: MongoDB&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;강력한&lt;span&gt; &lt;/span&gt;보안&lt;span&gt; &lt;/span&gt;기능을&lt;span&gt; &lt;/span&gt;제공하지만&lt;span&gt;, &lt;/span&gt;일부&lt;span&gt; &lt;/span&gt;고급&lt;span&gt; &lt;/span&gt;보안&lt;span&gt; &lt;/span&gt;요구사항을&lt;span&gt; &lt;/span&gt;충족시키기&lt;span&gt; &lt;/span&gt;위해서는&lt;span&gt; &lt;/span&gt;추가적인&lt;span&gt; &lt;/span&gt;설정과&lt;span&gt; &lt;/span&gt;관리가&lt;span&gt; &lt;/span&gt;필요할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;몽고 DB의 Index&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: left;&quot;&gt;- index는 한 쿼리에 한 index만 유효합니다. &lt;span style=&quot;color: #000000; text-align: left;&quot;&gt;따라서 두 개의 index 가 필요하다면 복합 index를 사용합니다.&lt;br /&gt;- &lt;/span&gt;&lt;/span&gt;index는 read 작업 위주의 애플리케션에서 유용하고 읽기보다 쓰기 작업이 많으면 index를 추가하는 것은 고려해야 합니다.&lt;/p&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;Single Field Index(&lt;span&gt;단일&lt;/span&gt; &lt;span&gt;필드&lt;/span&gt; &lt;span&gt;인덱스&lt;/span&gt;)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하나의 필드 인덱스를 사용&lt;/b&gt;하는 것을 단일 필드 인덱스라고 합니다. MongoDB에는 기본적으로 컬렉션에 _id라는 단일 필드 인덱스가 생성됩니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단일&lt;span&gt; &lt;/span&gt;필드&lt;span&gt; &lt;/span&gt;추가&lt;span&gt; &lt;/span&gt;방법은&lt;span&gt; &lt;/span&gt;아래와&lt;span&gt; &lt;/span&gt;같습니다&lt;span&gt;. &lt;/span&gt;원하는&lt;span&gt; field&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;입력합니다&lt;span&gt;.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;단일&lt;span&gt; &lt;/span&gt;필드&lt;span&gt; &lt;/span&gt;인덱스에서는&lt;span&gt; 1&lt;/span&gt;은&lt;span&gt; &lt;/span&gt;오름차순&lt;span&gt; -1&lt;/span&gt;은&lt;span&gt; &lt;/span&gt;내림차순을&lt;span&gt; &lt;/span&gt;의미합니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;하지만&lt;span&gt; &lt;/span&gt;단일&lt;span&gt; &lt;/span&gt;필드&lt;span&gt; &lt;/span&gt;인덱스에서는&lt;span&gt; &lt;/span&gt;오름차순인지&lt;span&gt; &lt;/span&gt;내림차순인지&lt;span&gt; &lt;/span&gt;중요하지&lt;span&gt; &lt;/span&gt;않습니다&lt;span&gt;.&amp;nbsp;&lt;br /&gt;&lt;/span&gt;왜냐하면&lt;span&gt; &lt;/span&gt;어떤&lt;span&gt; &lt;/span&gt;방향으로&lt;span&gt; &lt;/span&gt;가도&lt;span&gt; &lt;/span&gt;동일하게&lt;span&gt; &lt;/span&gt;접근하기&lt;span&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;pre id=&quot;code_1713798669009&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; db.user.createIndex({score: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;h4 data-ke-size=&quot;size20&quot;&gt;Compound Index(&lt;span&gt;복합&lt;/span&gt; &lt;span&gt;인덱스&lt;/span&gt;)&lt;/h4&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;span&gt; &lt;/span&gt;같이&lt;span&gt; &lt;/span&gt;인덱스를&lt;span&gt; &lt;/span&gt;생성한다면&lt;span&gt;, &lt;/span&gt;아래&lt;span&gt; &lt;/span&gt;그림과&lt;span&gt; &lt;/span&gt;같이&lt;span&gt; userid&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;오름차순으로&lt;span&gt; &lt;/span&gt;정렬됩니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;그리고&lt;span&gt; &lt;/span&gt;같은&lt;span&gt; userid&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;지니면&lt;span&gt; score&lt;/span&gt;로&lt;span&gt; &lt;/span&gt;내림차순&lt;span&gt; &lt;/span&gt;정렬하게&lt;span&gt; &lt;/span&gt;됩니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;예를&lt;span&gt; &lt;/span&gt;들면&lt;span&gt; &lt;/span&gt;동일한&lt;span&gt; userid &lt;/span&gt;인&lt;span&gt;&quot;ca2&quot;&lt;/span&gt;는&lt;span&gt; score&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;내림차순으로&lt;span&gt; &lt;/span&gt;정렬되어&lt;span&gt; &lt;/span&gt;있음을&lt;span&gt; &lt;/span&gt;그림에서&lt;span&gt; &lt;/span&gt;확인할&lt;span&gt; &lt;/span&gt;수&lt;span&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;pre id=&quot;code_1713798783709&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;gt; db.user.createIndex({userid:1 ,score:-1})&lt;/code&gt;&lt;/pre&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;720&quot; data-origin-height=&quot;260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FmMpA/btsGQRnoo3I/zvAKQkiWkukoQ1Re6cnU10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FmMpA/btsGQRnoo3I/zvAKQkiWkukoQ1Re6cnU10/img.png&quot; data-alt=&quot;ttps://docs.mongodb.com/manual/core/index-compound/&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FmMpA/btsGQRnoo3I/zvAKQkiWkukoQ1Re6cnU10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFmMpA%2FbtsGQRnoo3I%2FzvAKQkiWkukoQ1Re6cnU10%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;720&quot; height=&quot;260&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;ttps://docs.mongodb.com/manual/core/index-compound/&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;- 특징 1. sort 연산 시 인덱스 순서를 고려하여 생성하자.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;복합 인덱스에서는 키의 순서가 매우 중요합니다. 만일 복합 인덱스에서 순서가 userid-score가 아니라 score-userid로 생성하는 것은 다른 인덱스를 생성한 것입니다.&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;예를 들어 아래와 같이 인덱스 a-b순서로 생성하면 a-b 정렬은 지원을 하지만, b-a로 정렬은 지원하지 않습니다.&lt;/p&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;- 특징 2. 단일 인덱스와 다르게 복합 인덱스는 정렬 방향을 고려하자.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;검색&lt;span&gt; &lt;/span&gt;쿼리에서&lt;span&gt; &lt;/span&gt;복합&lt;span&gt; &lt;/span&gt;인덱스를&lt;span&gt; &lt;/span&gt;사용하는&lt;span&gt; &lt;/span&gt;경우&lt;span&gt; &lt;/span&gt;지정된&lt;span&gt; &lt;/span&gt;정렬&lt;span&gt; &lt;/span&gt;방향은&lt;span&gt; index&lt;/span&gt;와&lt;span&gt; &lt;/span&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;span&gt; &lt;/span&gt;아래와&lt;span&gt; &lt;/span&gt;같이&lt;span&gt; &lt;/span&gt;두&lt;span&gt; &lt;/span&gt;필드&lt;span&gt; &lt;/span&gt;정렬이&lt;span&gt; &lt;/span&gt;역으로&lt;span&gt; &lt;/span&gt;생성된&lt;span&gt; &lt;/span&gt;경우라면&lt;span&gt; &lt;/span&gt;역으로&lt;span&gt; &lt;/span&gt;조회하는&lt;span&gt; &lt;/span&gt;쿼리는&lt;span&gt; &lt;/span&gt;지원하지만&lt;span&gt;, &lt;/span&gt;동일한&lt;span&gt; &lt;/span&gt;정렬을&lt;span&gt; &lt;/span&gt;하는&lt;span&gt; &lt;/span&gt;쿼리는&lt;span&gt; &lt;/span&gt;지원하지&lt;span&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;사용 TIPS &lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mongoDB 핸즈온 워크샵에서 들은 내용들..&lt;br /&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;size18&quot;&gt;&lt;b&gt;Insert Replication&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;기본 3개의 노드로 구성된 클러스터 환경으로 데이터 복제를 위한 옵션 제공&lt;/li&gt;
&lt;li&gt;비동기 형태의 보장하기 위해 write concern 제공&lt;/li&gt;
&lt;li&gt;Default한 설정 권장&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;Array Search 시&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;Array 검색 시 elemMatch 사용&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Index&lt;/b&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;Single Field { year: 1 }&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/span&gt;ASC : 1, DESC: -1&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;Compound Field { year: 1, rated: -1 }&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Multikey { languages: 1 }&lt;br /&gt;Array index&lt;br /&gt;include element search&lt;/li&gt;
&lt;li&gt;Geospatial &lt;br /&gt;x B-tree&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Text&lt;br /&gt;한국에서 사용하기 어렵 -&amp;gt; altas search 대체&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;Hashed { did: hashed }&lt;br /&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;&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;Query plan&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;winningPlan 위주로&lt;/li&gt;
&lt;li&gt;COLLSCAN 무조건 지양 -&amp;gt; 무조건 index를 통한 SCAN&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;인덱스 생성 시 고려사항(ESR) - 아래 순서대로 인덱스 구성&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;Equality (최대한 앞으로)&lt;/li&gt;
&lt;li&gt;Sorting&lt;/li&gt;
&lt;li&gt;Range&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필드 지정 순서에 대한 고려&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쿼리 패턴을 고려&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;읽어들인&lt;span&gt; &lt;/span&gt;인덱스키와&lt;span&gt; document&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;같을&lt;span&gt; &lt;/span&gt;수록&lt;span&gt; &lt;/span&gt;성능이&lt;span&gt; &lt;/span&gt;좋다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Back-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/225</guid>
      <comments>https://hmk1022.tistory.com/entry/%EB%AA%BD%EA%B3%A0%EB%94%94%EB%B9%84%EB%9E%80-mongoDB#entry225comment</comments>
      <pubDate>Tue, 23 Apr 2024 00:14:50 +0900</pubDate>
    </item>
    <item>
      <title>리액트 성능 측정 &amp;amp; 개선하기  (feat. memo &amp;amp; React DevTools)</title>
      <link>https://hmk1022.tistory.com/entry/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%84%B1%EB%8A%A5-%EC%B8%A1%EC%A0%95%ED%95%98%EA%B8%B0-memo-feat-React-DevTools</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;리액트 성능 측정하기 - 효율적인 테이블 컴포넌트 구현&lt;br /&gt;&lt;br /&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;&lt;br /&gt;&lt;b&gt;1. 페이징 처리가 없는 테이블의 형태&lt;/b&gt;&lt;br /&gt;&lt;b&gt;2. 옵션값 개수의 모든 경우의 수를 고려한 옵션생성(수십 ~ 수백 개의 테이블 row UI가 생김)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 판매 마켓별로 옵션들의 값을 수정할 수 있는 UI&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;4. 테이블 데이터(옵션)들을 일괄변경 할 수 있는 기능(자주 사용할 것으로 판단)&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;특히 수백 개의 테이블 row가 재렌더링 되는 경우, 애플리케이션의 성능 저하가 발생할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;성능 측정과 개선&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성능 측정은 React DevTools의 Profiler를 이용했습니다.&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/b3i7Qw/btsGMSHghoN/20KKMnyuk96nkPJwigQaGK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3i7Qw/btsGMSHghoN/20KKMnyuk96nkPJwigQaGK/img.jpg&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot; data-is-animation=&quot;false&quot; width=&quot;545&quot; height=&quot;307&quot; style=&quot;width: 57.4104%; margin-right: 10px;&quot; data-widthpercent=&quot;58.09&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3i7Qw/btsGMSHghoN/20KKMnyuk96nkPJwigQaGK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3i7Qw%2FbtsGMSHghoN%2F20KKMnyuk96nkPJwigQaGK%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;1280&quot; height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/L0o5D/btsGNfWoiJr/nCDOf9RXrKCgIj8JhiwpH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/L0o5D/btsGNfWoiJr/nCDOf9RXrKCgIj8JhiwpH0/img.png&quot; data-origin-width=&quot;254&quot; data-origin-height=&quot;198&quot; data-is-animation=&quot;false&quot; style=&quot;width: 41.4268%;&quot; data-widthpercent=&quot;41.91&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/L0o5D/btsGNfWoiJr/nCDOf9RXrKCgIj8JhiwpH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FL0o5D%2FbtsGNfWoiJr%2FnCDOf9RXrKCgIj8JhiwpH0%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;254&quot; height=&quot;198&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&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;/h4&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;2.7s&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테이블 렌더링 소요 시간 - &lt;b&gt;87.3ms&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vHJJD/btsGLIL7fV7/s2TXPlXjbTyaIkhXZin7FK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vHJJD/btsGLIL7fV7/s2TXPlXjbTyaIkhXZin7FK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vHJJD/btsGLIL7fV7/s2TXPlXjbTyaIkhXZin7FK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvHJJD%2FbtsGLIL7fV7%2Fs2TXPlXjbTyaIkhXZin7FK%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;446&quot; height=&quot;180&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;180&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2512&quot; data-origin-height=&quot;843&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnwltn/btsGN0K3y4v/a3kSPGhsZjOG1EVhxv3UcK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnwltn/btsGN0K3y4v/a3kSPGhsZjOG1EVhxv3UcK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnwltn/btsGN0K3y4v/a3kSPGhsZjOG1EVhxv3UcK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbnwltn%2FbtsGN0K3y4v%2Fa3kSPGhsZjOG1EVhxv3UcK%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;2512&quot; height=&quot;843&quot; data-origin-width=&quot;2512&quot; data-origin-height=&quot;843&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1470&quot; data-origin-height=&quot;693&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctJORk/btsGMfXgfvy/tCVNAACdnXGLoySJk4bO3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctJORk/btsGMfXgfvy/tCVNAACdnXGLoySJk4bO3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctJORk/btsGMfXgfvy/tCVNAACdnXGLoySJk4bO3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctJORk%2FbtsGMfXgfvy%2FtCVNAACdnXGLoySJk4bO3k%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;1470&quot; height=&quot;693&quot; data-origin-width=&quot;1470&quot; data-origin-height=&quot;693&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Table Row 메모 적용 후&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 총 렌더링 소요 시간 -&lt;b&gt;&lt;span&gt; 1&lt;/span&gt;.7s&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;테이블 렌더링 소요 시간 -&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;85.3ms&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&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-origin-width=&quot;447&quot; data-origin-height=&quot;207&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dHRcOB/btsGMBeMu9D/BnMZu0kTGTxKlRrI4zxKgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dHRcOB/btsGMBeMu9D/BnMZu0kTGTxKlRrI4zxKgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dHRcOB/btsGMBeMu9D/BnMZu0kTGTxKlRrI4zxKgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdHRcOB%2FbtsGMBeMu9D%2FBnMZu0kTGTxKlRrI4zxKgK%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;447&quot; height=&quot;207&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;207&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;b&gt;적용코드&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1713621898174&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export const TableItem = React.memo(Component);&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2056&quot; data-origin-height=&quot;745&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8XqGB/btsGNq4xmZD/bx3MCvRxcfYg7q0qQzgcGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8XqGB/btsGNq4xmZD/bx3MCvRxcfYg7q0qQzgcGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8XqGB/btsGNq4xmZD/bx3MCvRxcfYg7q0qQzgcGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8XqGB%2FbtsGNq4xmZD%2Fbx3MCvRxcfYg7q0qQzgcGK%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;2056&quot; height=&quot;745&quot; data-origin-width=&quot;2056&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Table Cell 메모&lt;span&gt;&amp;nbsp;&lt;/span&gt;적용 후&amp;nbsp;&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;b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;1&lt;/span&gt;.4s&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;테이블 렌더링 소요 시간 -&lt;b&gt;&lt;span&gt; 27&lt;/span&gt;.6ms&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;아래의 UI를 보면 선택된 row와 선택된 row들의 데이터를 일괄 수정할 수 있는 버튼 UI가 보인다.&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;size16&quot;&gt;Row뿐만 아니라 &lt;b&gt;각 Cell에도 메모제이션을 적용하면 일괄 변경 시 성능상 이점&lt;/b&gt;을 가져갈 수 있을 것으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;판단해 각 Cell에 memo를 적용했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;187&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqZfKg/btsGNfvix6n/qgsCu9Oo6SYvTM2NcaN5I0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqZfKg/btsGNfvix6n/qgsCu9Oo6SYvTM2NcaN5I0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqZfKg/btsGNfvix6n/qgsCu9Oo6SYvTM2NcaN5I0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqZfKg%2FbtsGNfvix6n%2FqgsCu9Oo6SYvTM2NcaN5I0%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;855&quot; height=&quot;187&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;187&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxXSbZ/btsGMec0cnh/zZzCQDZY4cuKYisk9ubHT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxXSbZ/btsGMec0cnh/zZzCQDZY4cuKYisk9ubHT1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxXSbZ/btsGMec0cnh/zZzCQDZY4cuKYisk9ubHT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxXSbZ%2FbtsGMec0cnh%2FzZzCQDZY4cuKYisk9ubHT1%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;445&quot; height=&quot;138&quot; data-origin-width=&quot;445&quot; data-origin-height=&quot;138&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;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;아래와 같이 각 Cell에 memo를 적용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 &lt;b&gt;memo는 얕은 비교를 수행&lt;/b&gt;해 참조형 데이터를 props로 받는 cell의 경우엔 아래와 같이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- memo shallow eqaul 참고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://react.dev/reference/react/memo#specifying-a-custom-comparison-function:~:text=between%20re%2Drenders.-,Specifying%20a%20custom%20comparison%20function,-In%20rare%20cases&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://react.dev/reference/react/memo#specifying-a-custom-comparison-function:~:text=between%20re%2Drenders.-,Specifying%20a%20custom%20comparison%20function,-In%20rare%20cases&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1713622827138&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;memo &amp;ndash; React&quot; data-og-description=&quot;The library for web and native user interfaces&quot; data-og-host=&quot;react.dev&quot; data-og-source-url=&quot;https://react.dev/reference/react/memo#specifying-a-custom-comparison-function:~:text=between%20re%2Drenders.-,Specifying%20a%20custom%20comparison%20function,-In%20rare%20cases&quot; data-og-url=&quot;https://react.dev/reference/react/memo&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Nkjiu/hyVSTpUkbp/fia9J3mq2LFg2jLt25w8x0/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567,https://scrap.kakaocdn.net/dn/g6Np2/hyVSYSfd9S/vDyiaSNFKQ1ifpSls1KNx1/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567&quot;&gt;&lt;a href=&quot;https://react.dev/reference/react/memo#specifying-a-custom-comparison-function:~:text=between%20re%2Drenders.-,Specifying%20a%20custom%20comparison%20function,-In%20rare%20cases&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://react.dev/reference/react/memo#specifying-a-custom-comparison-function:~:text=between%20re%2Drenders.-,Specifying%20a%20custom%20comparison%20function,-In%20rare%20cases&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Nkjiu/hyVSTpUkbp/fia9J3mq2LFg2jLt25w8x0/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567,https://scrap.kakaocdn.net/dn/g6Np2/hyVSYSfd9S/vDyiaSNFKQ1ifpSls1KNx1/img.png?width=1080&amp;amp;height=567&amp;amp;face=0_0_1080_567');&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;memo &amp;ndash; React&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The library for web and native user interfaces&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;react.dev&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;size16&quot;&gt;&lt;b&gt;deep compare를 수행하는 lodash의 isEqual&lt;/b&gt;을 사용해 memo의 두 번째 인자에서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;props의 변화를 감지하는 방식으로 구현했습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1713622116198&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { isEqual } from 'lodash';

export const FinalPriceCell = React.memo(Component, (prevProps, nextProps) =&amp;gt; {
  return isEqual(prevProps, nextProps);
});&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React.memo()는 리액트에서 메모이제이션의 장점을 얻게 해 주는 훌륭한 도구다. &lt;br /&gt;올바르게 적용된다면 변경되지 않은 동일한 prop에 대해 리렌더링을 하는 것을 방지할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt; But,&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 무분별한 memo는 오히려 메모리 사용 증가로 성능상 저하를 유발할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 원시형이 아닌 참조형 데이터를 props로 넘길 때 memo가 의도대로 동작하지 않을 수 있으므로, 깊은 비교가 필요합니다.&lt;br /&gt;- 콜백 함수를 prop으로 사용하는 컴포넌트에서 메모이지을 할 때 주의가 필요합니다.&lt;br /&gt;- 같은 렌더링을 할 때 이전과 동일한 콜백 함수 인스턴스를 넘기는지 확인이 필요합니다.&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 메모이제이션의 성능상 이점을 측정하기 위해&lt;span&gt; profiler를 사용해 보는 것이 좋습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://react.dev/reference/react/memo&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://react.dev/reference/react/memo&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <category>React</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/224</guid>
      <comments>https://hmk1022.tistory.com/entry/%EB%A6%AC%EC%95%A1%ED%8A%B8-%EC%84%B1%EB%8A%A5-%EC%B8%A1%EC%A0%95%ED%95%98%EA%B8%B0-memo-feat-React-DevTools#entry224comment</comments>
      <pubDate>Sat, 20 Apr 2024 23:22:03 +0900</pubDate>
    </item>
    <item>
      <title>Sec-CH-UA(Security-ClientHint-UserAgent)</title>
      <link>https://hmk1022.tistory.com/entry/Sec-CH-UASecurity-ClientHint-UserAgent</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;웹 브라우저의 보안 클라이언트 힌트 (Sec-CH-UA) 이해하기&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 브라우저는 서버에게 어떻게 동작하고 어떤 환경에서 실행되고 있는지에 대한 정보를 전송하기 위해 다양한 헤더를 사용합니다. 이 중에서도 &quot;Sec-CH-UA&quot; 헤더는 보안 클라이언트 힌트의 사용자 에이전트 정보를 제공하는 중요한 역할을 합니다. 이번 글에서는 &quot;Sec-CH-UA&quot; 헤더의 각 필드에 대해 자세히 알아보겠습니다.&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;1200&quot; data-origin-height=&quot;953&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ACU3E/btsGGjRW05s/OcAGs8Dvks2HHebiO1YmX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ACU3E/btsGGjRW05s/OcAGs8Dvks2HHebiO1YmX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ACU3E/btsGGjRW05s/OcAGs8Dvks2HHebiO1YmX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FACU3E%2FbtsGGjRW05s%2FOcAGs8Dvks2HHebiO1YmX0%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;594&quot; height=&quot;472&quot; data-origin-width=&quot;1200&quot; data-origin-height=&quot;953&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;span&gt;&quot;Sec-CH-UA&quot;&lt;/span&gt;와&lt;span&gt; &lt;/span&gt;관련된&lt;span&gt; &lt;/span&gt;헤더는&lt;span&gt; &lt;/span&gt;주로&lt;span&gt; &lt;/span&gt;&lt;b&gt;웹&lt;span&gt; &lt;/span&gt;브라우저에&lt;span&gt; &lt;/span&gt;의해&lt;span&gt; &lt;/span&gt;자동으로&lt;span&gt; &lt;/span&gt;생성&lt;/b&gt;되며&lt;span&gt;, &lt;/span&gt;클라이언트&lt;span&gt; &lt;/span&gt;측에서&lt;span&gt; &lt;/span&gt;서버에&lt;span&gt; &lt;/span&gt;전송됩니다&lt;span&gt;. &lt;/span&gt;이&lt;span&gt; &lt;/span&gt;헤더는&lt;span&gt; &lt;/span&gt;브라우저의&lt;span&gt; &lt;/span&gt;사용자&lt;span&gt; &lt;/span&gt;에이전트&lt;span&gt; &lt;/span&gt;정보와&lt;span&gt; &lt;/span&gt;함께&lt;span&gt; &lt;/span&gt;웹&lt;span&gt; &lt;/span&gt;페이지&lt;span&gt; &lt;/span&gt;요청에&lt;span&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 data-ke-size=&quot;size16&quot;&gt;유저가 어떤 환경에서 우리 서비스를 사용하는지에 대한 정보를 수집할 수도 있으며&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹사이트 크롤링을 방어할 때&amp;nbsp; Sec-CH-UA 포함 여부를 검사해 브라우저에서 보낸 요청인지 식별하는 경우가 꽤 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;도입이유&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 User-Agent HTTP 헤더&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;에서 브라우저, OS, 사용자의 기기 정보 등 사용자 에이전트 정보를 얻을 수 있었음&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;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;But&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #555555; text-align: start;&quot;&gt;User-Agent string에는 많은 엔트로피(정보량)가 담겨 있어 개&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;color: #555555; text-align: start;&quot;&gt;Chrome은 이러한 문제를 해결하고자 &lt;b&gt;Client Hints를 헤더에 포함하는 방향&lt;/b&gt;으로 변경&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Sec-CH-UA&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Google Chrome&lt;/b&gt;: 버전 &quot;123&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Not:A-Brand&lt;/b&gt;: 버전 &quot;8&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Chromium&lt;/b&gt;: 버전 &quot;123&quot;&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;헤더의 가장 기본적인 필드는 웹 브라우저의 이름과 버전 정보입니다. 위의 예시에서는 &quot;Google Chrome&quot;, &quot;Not:A-Brand&quot;, &quot;Chromium&quot; 등의 브라우저들과 그들의 버전 정보가 포함되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Sec-CH-UA-Arch&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Arch&lt;/b&gt;: &quot;arm&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 필드는 웹 브라우저가 실행되고 있는 아키텍처 정보를 제공합니다. 예시에서는 &quot;arm&quot; 아키텍처를 사용하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Sec-CH-UA-Bitness&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;Bitness&lt;/b&gt;: &quot;64&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 브라우저의 비트 버전 정보를 나타냅니다. 위의 예시에서는 64비트 버전을 사용하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Sec-CH-UA-Full-Version-List&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Google Chrome&lt;/b&gt;: &quot;123.0.6312.122&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Not:A-Brand&lt;/b&gt;: &quot;8.0.0.0&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Chromium&lt;/b&gt;: &quot;123.0.6312.122&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Sec-CH-UA-Mobile&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Mobile:? 0&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 브라우저가 모바일 장치에서 실행되고 있는지의 여부를 나타냅니다. &quot;?&quot;는 이 필드의 값이 불분명하다는 것을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Sec-CH-UA-Model&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Model&lt;/b&gt;: &quot;&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Sec-CH-UA-Platform&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Platform&lt;/b&gt;: &quot;macOS&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Sec-CH-UA-Platform-Version&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Platform Version&lt;/b&gt;: &quot;13.2.1&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Sec-CH-UA-Wow64&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Wow64:? 0&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 필드는 웹 브라우저가 32비트 환경에서 64비트 애플리케이션으로 실행되고 있는지의 여부를 나타냅니다.&lt;/p&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;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;b&gt;Reference&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;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-CH-UA&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-CH-UA&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/223</guid>
      <comments>https://hmk1022.tistory.com/entry/Sec-CH-UASecurity-ClientHint-UserAgent#entry223comment</comments>
      <pubDate>Tue, 16 Apr 2024 22:39:32 +0900</pubDate>
    </item>
    <item>
      <title>마이크로 프론트엔드(Micro Frontend)</title>
      <link>https://hmk1022.tistory.com/entry/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9CMicro-Frontend</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;마이크로 프런트엔드란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;마이크로 프런트엔드는 &lt;b&gt;소규모 프런트엔드 서비스를 독립적으로 개발, 배포, 운영할 수 있게 하는 아키텍처 패턴.&lt;/b&gt; &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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;독립적인 개발 및 배포&lt;/b&gt;: 각 마이크로 프런트엔드는 독립적으로 개발, 테스트, 배포할 수 있어 더 빠르게 애플리케이션을 개선하고 배포할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;기술 스택의 유연성&lt;/b&gt;: 마이크로 프론트엔드 아키텍처는 다양한 프런트엔드 기술 스택을 사용할 수 있어 팀이 선호하는 기술을 선택하여 개발할 수 있습니다. (React, Vue, Svelte 등등)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;재사용성 및 확장성&lt;/b&gt;: 기능이나 컴포넌트를 재사용하거나, 새로운 기능을 추가할 때 각 마이크로 프런트엔드를 독립적으로 업데이트할 수 있어 확장성이 좋습니다.&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;팀&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;간&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;협업&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;용이성&lt;/b&gt;&lt;span&gt;: &lt;/span&gt;서로&lt;span&gt; &lt;/span&gt;다른&lt;span&gt; &lt;/span&gt;팀이나&lt;span&gt; &lt;/span&gt;조직이&lt;span&gt; &lt;/span&gt;독립적으로&lt;span&gt; &lt;/span&gt;개발할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있어&lt;span&gt; &lt;/span&gt;팀&lt;span&gt; &lt;/span&gt;간&lt;span&gt; &lt;/span&gt;협업이&lt;span&gt; &lt;/span&gt;더&lt;span&gt; &lt;/span&gt;유연해집니다&lt;span&gt;.&lt;br /&gt;&lt;/span&gt;&lt;span&gt;&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-origin-width=&quot;586&quot; data-origin-height=&quot;340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rJoM4/btsGCckGjY4/24zcX9lLr8lr5JtKv9m1v1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rJoM4/btsGCckGjY4/24zcX9lLr8lr5JtKv9m1v1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rJoM4/btsGCckGjY4/24zcX9lLr8lr5JtKv9m1v1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrJoM4%2FbtsGCckGjY4%2F24zcX9lLr8lr5JtKv9m1v1%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;586&quot; height=&quot;340&quot; data-origin-width=&quot;586&quot; data-origin-height=&quot;340&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;장점&lt;/span&gt;&lt;/h4&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;- FE 개발의 점진적 업그레이드 / 재작성이 용이해진다.&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;단점&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Micro Frontend 통합 방법&lt;/h3&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;1041&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEhvAO/btsGBbfXFBI/WHkDCszW2tmzgK1Mb57pVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEhvAO/btsGBbfXFBI/WHkDCszW2tmzgK1Mb57pVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEhvAO/btsGBbfXFBI/WHkDCszW2tmzgK1Mb57pVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEhvAO%2FbtsGBbfXFBI%2FWHkDCszW2tmzgK1Mb57pVk%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;1041&quot; height=&quot;349&quot; data-origin-width=&quot;1041&quot; data-origin-height=&quot;349&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;/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;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;각 서버로 html을 요청하고, 최종 응답 서버에서 각 템플릿을 조합해서 응답을 보냄&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;355&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IL2Fv/btsGAA8pnlw/hVpurQKaJkPVZHc0rvvzR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IL2Fv/btsGAA8pnlw/hVpurQKaJkPVZHc0rvvzR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IL2Fv/btsGAA8pnlw/hVpurQKaJkPVZHc0rvvzR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIL2Fv%2FbtsGAA8pnlw%2FhVpurQKaJkPVZHc0rvvzR0%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;683&quot; height=&quot;355&quot; data-origin-width=&quot;683&quot; data-origin-height=&quot;355&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;size18&quot;&gt;&lt;b&gt;빌드타임 통합 &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단위 애플리케이션을 패키지로 배포하고, package.json에 명시한 후 컨테이너 애플리케이션에서 import 하여 사용함&lt;/p&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;- 대표적으로 webpack의&amp;nbsp;&lt;a href=&quot;https://webpack.kr/concepts/module-federation/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Module Federation&lt;/a&gt;과 같은 방식이 있음&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PIesB/btsGCo6ueMj/QtNdKeMlP6ucT6kqhm3wpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PIesB/btsGCo6ueMj/QtNdKeMlP6ucT6kqhm3wpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PIesB/btsGCo6ueMj/QtNdKeMlP6ucT6kqhm3wpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPIesB%2FbtsGCo6ueMj%2FQtNdKeMlP6ucT6kqhm3wpk%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;733&quot; height=&quot;573&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;720&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;size18&quot;&gt;&lt;b&gt;iframe 통합&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;- routing, history, deep-link 같은 것들을 고려해야 함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 컨테이너 애플리케이션과 iframe에 들어가는 단위 애플리케이션 간의 통신규약 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- UX가 iframe안에 갇히기 때문에 어색한 UI가 표현될 수 있음&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;166&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bo9RAo/btsGB9O23wt/VTYyXjxL8Srz6VCbFdedwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bo9RAo/btsGB9O23wt/VTYyXjxL8Srz6VCbFdedwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bo9RAo/btsGB9O23wt/VTYyXjxL8Srz6VCbFdedwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbo9RAo%2FbtsGB9O23wt%2FVTYyXjxL8Srz6VCbFdedwK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;166&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;166&quot;/&gt;&lt;/span&gt;&lt;/figure&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; Javascript를 통한 런타임 통합&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;iframe과 달리 유연한 통합이 가능&lt;/p&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;script&amp;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;size18&quot;&gt;&amp;nbsp;&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;WebComponent를 통한 통합&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML 엘리먼트를 통한 방법으로, static, runtime 둘 다 가능한 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- javascript 런타임 통합과 비슷하지만 &quot;The web component way&quot;를 지향한다.&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;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;도입 전에 고려해봐야 할 것들&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;어느 정도 복잡성을 가진 시스템에서 유용하므로 관리 자원과 트레이드오프를 생각해 신중하게 도입&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;- 모노레포 도입으로 효율적인 의존성 관리 (공통 항목 단일화, Package 공유, 단일 이슈트래킹)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 분산된 CI 보다 속도가 느릴 수 있음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://kdydesign.github.io/2020/08/27/mono-repo-lerna-example/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;lerna&lt;/a&gt; 같은 툴을 도입해 관리해보기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style3&quot; data-ke-type=&quot;horizontalRule&quot; /&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;/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;a href=&quot;https://toss.tech/article/node-modules-and-yarn-berry&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;yarn berry 도입&lt;/a&gt; 및 zero install 사용 (빌드 시간을 줄이기 위해 변경사항이 없는 패키지는 빌드하지 않도록)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;UI의 일관성을 위해 UI Component Library를 만들어 관리하기&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;애플리케이션 간의 통신은 Custom events를 사용하기&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&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #5c7e9f;&quot; href=&quot;https://github.com/mroderick/PubSubJS&quot;&gt;PubSubJS&lt;/a&gt;를 고려해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 호출 시 URL 라우팅에 넘기기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;백엔드 호출 API 구성&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;- BFF(Backend for Frontend Pattern) 패턴으로 프런트엔드 전용 API를 갖는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 별도의 데이터베이스를 구성할 수도&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 로그인 같은 보안정보들은 통합하는 Container에서 관리하기&lt;/p&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bk2jUY/btsGBOkgPSs/8eydWMfEtPXyDhodbxEWr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bk2jUY/btsGBOkgPSs/8eydWMfEtPXyDhodbxEWr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bk2jUY/btsGBOkgPSs/8eydWMfEtPXyDhodbxEWr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbk2jUY%2FbtsGBOkgPSs%2F8eydWMfEtPXyDhodbxEWr0%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;731&quot; height=&quot;324&quot; data-origin-width=&quot;731&quot; data-origin-height=&quot;324&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Reference&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;&lt;a href=&quot;https://mobicon.tistory.com/572&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://mobicon.tistory.com/572&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1713001956199&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;[Micro Frontend] 마이크로 프론트앤드 - 개념&quot; data-og-description=&quot;마이크로 프론트앤드는 마이크로 서비스처럼 전체 화면을 작동할 수 있는 단위로 나누어 개발한 후 서로 조립하는 방식이다. 여기서 작동 단위에 사용된 프론트앤드 프레임워크로 Angular 이든, R&quot; data-og-host=&quot;mobicon.tistory.com&quot; data-og-source-url=&quot;https://mobicon.tistory.com/572&quot; data-og-url=&quot;https://mobicon.tistory.com/572&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/wydgA/hyVMXfY51z/qwkYfmCXGrc07m2SRuMsZ0/img.png?width=586&amp;amp;height=340&amp;amp;face=0_0_586_340,https://scrap.kakaocdn.net/dn/dtqiv4/hyVMSZ8k0t/fLdyVWAVdK9DJdCFnlunB1/img.png?width=586&amp;amp;height=340&amp;amp;face=0_0_586_340,https://scrap.kakaocdn.net/dn/oCYhh/hyVPPHqvoA/0k5rJLkrXsKKOiBNVFXMu1/img.png?width=731&amp;amp;height=324&amp;amp;face=0_0_731_324&quot;&gt;&lt;a href=&quot;https://mobicon.tistory.com/572&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://mobicon.tistory.com/572&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/wydgA/hyVMXfY51z/qwkYfmCXGrc07m2SRuMsZ0/img.png?width=586&amp;amp;height=340&amp;amp;face=0_0_586_340,https://scrap.kakaocdn.net/dn/dtqiv4/hyVMSZ8k0t/fLdyVWAVdK9DJdCFnlunB1/img.png?width=586&amp;amp;height=340&amp;amp;face=0_0_586_340,https://scrap.kakaocdn.net/dn/oCYhh/hyVPPHqvoA/0k5rJLkrXsKKOiBNVFXMu1/img.png?width=731&amp;amp;height=324&amp;amp;face=0_0_731_324');&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;[Micro Frontend] 마이크로 프론트앤드 - 개념&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;마이크로 프론트앤드는 마이크로 서비스처럼 전체 화면을 작동할 수 있는 단위로 나누어 개발한 후 서로 조립하는 방식이다. 여기서 작동 단위에 사용된 프론트앤드 프레임워크로 Angular 이든, R&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;mobicon.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;&lt;a href=&quot;https://velog.io/@dalbodre_ari/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%99%80-%EB%AA%A8%EB%85%B8%EB%A0%88%ED%8F%AC-%EC%A0%9C%EB%A1%9C%EB%B9%8C%EB%93%9C&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://velog.io/@dalbodre_ari/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%99%80-%EB%AA%A8%EB%85%B8%EB%A0%88%ED%8F%AC-%EC%A0%9C%EB%A1%9C%EB%B9%8C%EB%93%9C&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1713004145710&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;마이크로 프론트엔드와 모노레포 &amp;amp; 제로빌드&quot; data-og-description=&quot;이것은 마치 까먹지 않기 위해 정리하는 메모장이랄까.. toss slash21 보고나서 언젠가 정리해야지 미루고 미뤘는데.. 곳곳의 세미나에서 마이크로 프론트엔드 도입기를 자랑하기 시작했다,,,,,&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@dalbodre_ari/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%99%80-%EB%AA%A8%EB%85%B8%EB%A0%88%ED%8F%AC-%EC%A0%9C%EB%A1%9C%EB%B9%8C%EB%93%9C&quot; data-og-url=&quot;https://velog.io/@dalbodre_ari/마이크로-프론트엔드와-모노레포-제로빌드&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/8Km9A/hyVPPgmmKY/ZNpXeEYjwmvwIM8sz8EBq0/img.jpg?width=1024&amp;amp;height=768&amp;amp;face=721_380_895_570,https://scrap.kakaocdn.net/dn/IlMzZ/hyVMX1pBzv/eCuOrK79MKdDSrmN2GzUU1/img.jpg?width=1024&amp;amp;height=768&amp;amp;face=721_380_895_570,https://scrap.kakaocdn.net/dn/bPUWK2/hyVPMxaVxY/hqoaFmPg2sS1mtnfCC38T0/img.png?width=2220&amp;amp;height=1186&amp;amp;face=416_433_2080_1084&quot;&gt;&lt;a href=&quot;https://velog.io/@dalbodre_ari/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%99%80-%EB%AA%A8%EB%85%B8%EB%A0%88%ED%8F%AC-%EC%A0%9C%EB%A1%9C%EB%B9%8C%EB%93%9C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@dalbodre_ari/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%99%80-%EB%AA%A8%EB%85%B8%EB%A0%88%ED%8F%AC-%EC%A0%9C%EB%A1%9C%EB%B9%8C%EB%93%9C&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/8Km9A/hyVPPgmmKY/ZNpXeEYjwmvwIM8sz8EBq0/img.jpg?width=1024&amp;amp;height=768&amp;amp;face=721_380_895_570,https://scrap.kakaocdn.net/dn/IlMzZ/hyVMX1pBzv/eCuOrK79MKdDSrmN2GzUU1/img.jpg?width=1024&amp;amp;height=768&amp;amp;face=721_380_895_570,https://scrap.kakaocdn.net/dn/bPUWK2/hyVPMxaVxY/hqoaFmPg2sS1mtnfCC38T0/img.png?width=2220&amp;amp;height=1186&amp;amp;face=416_433_2080_1084');&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;마이크로 프론트엔드와 모노레포 &amp;amp; 제로빌드&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이것은 마치 까먹지 않기 위해 정리하는 메모장이랄까.. toss slash21 보고나서 언젠가 정리해야지 미루고 미뤘는데.. 곳곳의 세미나에서 마이크로 프론트엔드 도입기를 자랑하기 시작했다,,,,,&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.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>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/222</guid>
      <comments>https://hmk1022.tistory.com/entry/%EB%A7%88%EC%9D%B4%ED%81%AC%EB%A1%9C-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9CMicro-Frontend#entry222comment</comments>
      <pubDate>Sat, 13 Apr 2024 19:30:11 +0900</pubDate>
    </item>
    <item>
      <title>자바스크립트와 V8</title>
      <link>https://hmk1022.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%99%80-V8</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;마이크로프로세서( CPU)&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;일단 V8엔진에 대해서 설명하기 전에 우리가 작성한 javscsript 코드가 어떻게 실행되는지 아주 간단하게 훑어보자&lt;/p&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;마이크로프로세서(CPU)&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;우리는 마이크로프로세서에게 지시(instruction)를 주고 마이크로프로세서는 job을 수행한다.&lt;/p&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;IA-32, x86-64, MIPS 그리고 ARM이 있다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;559&quot; data-origin-height=&quot;340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckHETK/btsGvpS4jRa/CDliWyDkFSFxjwtw9O2Zz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckHETK/btsGvpS4jRa/CDliWyDkFSFxjwtw9O2Zz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckHETK/btsGvpS4jRa/CDliWyDkFSFxjwtw9O2Zz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckHETK%2FbtsGvpS4jRa%2FCDliWyDkFSFxjwtw9O2Zz0%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;474&quot; height=&quot;288&quot; data-origin-width=&quot;559&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;음.. 사실 위의 내용엔 약간의 오류가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;V8 엔진은 javascript를 기계어가 아닌 바이트 코드로 컴파일한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 아래 V8엔진의 작동원리의 컴파일 단계에서 적어놓았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;V8 엔진의 작동원리를 살표 보는 이유&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;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;자바스크립트로 뽑아낼 수 있는 최적의 성능을 사용하고 싶다면 &lt;br /&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;V8 엔진이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글이 주도하여 C++로 작성된&amp;nbsp; 고성능의 자바스크립트 &amp;amp; 웹어셉블리 엔진&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오픈 소스로 &lt;a href=&quot;https://github.com/v8/v8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;git repo&lt;/a&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;주로 Google Chrome과 NodeJS에서 사용되고 있으며, ECMAScript와 WebAssembly를 표준에 맞게 구현했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;V8 엔진의 작동원리&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;1. 파싱(Parsing)&lt;/h4&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;파싱은&amp;nbsp;코드를&amp;nbsp;추상&amp;nbsp;구문&amp;nbsp;트리(Abstract&amp;nbsp;Syntax&amp;nbsp;Tree,&amp;nbsp;AST)로&amp;nbsp;변환하는&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 최적화(Optimiaztion)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;V8 엔진은 추상 구문 트리를 최적화하는 단계를 거칩니다.&lt;br /&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;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 컴파일(Compilation):&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;최적화된&amp;nbsp;추상&amp;nbsp;구문&amp;nbsp;트리는&amp;nbsp;기계어로&amp;nbsp;변환됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &lt;b&gt;최적화된 코드를 바이트로 변환하는 Ignition&lt;/b&gt;이 실행됩니다.&lt;br /&gt;V8&amp;nbsp;엔진은&amp;nbsp;고성능&amp;nbsp;JIT(Just-In-Time)&amp;nbsp;컴파일러를&amp;nbsp;사용하여&amp;nbsp;코드를&amp;nbsp;컴파일합니다.&lt;br /&gt;JIT&amp;nbsp;컴파일러는&amp;nbsp;자주&amp;nbsp;사용되는&amp;nbsp;코드&amp;nbsp;블록을&amp;nbsp;미리&amp;nbsp;컴파일하여&amp;nbsp;성능을&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 id=&quot;ignition으로-바이트-코드bytecode-생성하기&quot; style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;Ignition으로 바이트 코드(Bytecode) 생성하기&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;150&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brNGkQ/btsGx05cwqu/wEd1BQfL0gR06FO9X2wnvk/tfile.svg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brNGkQ/btsGx05cwqu/wEd1BQfL0gR06FO9X2wnvk/tfile.svg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brNGkQ/btsGx05cwqu/wEd1BQfL0gR06FO9X2wnvk/tfile.svg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrNGkQ%2FbtsGx05cwqu%2FwEd1BQfL0gR06FO9X2wnvk%2Ftfile.svg&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;150&quot; height=&quot;150&quot; data-origin-width=&quot;150&quot; data-origin-height=&quot;150&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;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;자바스크립트는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;C++&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;과 같은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;정적 타이핑 언어&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&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: #000000; text-align: start;&quot;&gt;라서 &lt;br /&gt;소스 &lt;b&gt;코드가 실행되기 전에는 알 수 없는 값들이 너무 많았기 때문&lt;/b&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: #000000; text-align: start;&quot;&gt;그래서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Ignition&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;을 개발할 때는 모든 소스를 한 번에 해석하는 &lt;br /&gt;컴파일 방식이 아닌 코드 &lt;b&gt;한 줄 한 줄이 실행될 때마다 해석하는 인터프리트 방식을 채택&lt;/b&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;blockquote data-ke-style=&quot;style2&quot;&gt;1. 메모리 사용량 감소. 자바스크립트 코드에서 기계어로 컴파일하는 것보다 바이트 코드로 컴파일하는 것이 더 편하다.&lt;br /&gt;2. 파싱 시 오버헤드 감소. 바이트 코드는 간결하기 때문에 다시 파싱 하기도 편하다.&lt;br /&gt;3. 컴파일 파이프 라인의 복잡성 감소. Optimizing이든 Deoptimizing이든 바이트 코드 하나만 생각하면 되기 때문에 편하다.&lt;br /&gt;&lt;br /&gt;- Ross McIlroy Ignition - an interpreter for V8&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 말해서 Ignition은 &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;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TurboFan으로&amp;nbsp; 최적화하기&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;150&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjvyny/btsGxBeGqOm/Z4CNcp7jZpqpGTawtgIUFk/tfile.svg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjvyny/btsGxBeGqOm/Z4CNcp7jZpqpGTawtgIUFk/tfile.svg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjvyny/btsGxBeGqOm/Z4CNcp7jZpqpGTawtgIUFk/tfile.svg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbjvyny%2FbtsGxBeGqOm%2FZ4CNcp7jZpqpGTawtgIUFk%2Ftfile.svg&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;150&quot; height=&quot;150&quot; data-origin-width=&quot;150&quot; data-origin-height=&quot;150&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;span&gt;TurboFan&lt;/span&gt;은&lt;span&gt; &lt;/span&gt;최적화된&lt;span&gt; &lt;/span&gt;바이트코드를&lt;span&gt; &lt;/span&gt;기계어로&lt;span&gt; &lt;/span&gt;컴파일하는&lt;span&gt; &lt;/span&gt;역할을&lt;span&gt; &lt;/span&gt;합니다&lt;span&gt;. &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;TurboFan은 V8 엔진의 &lt;b&gt;최적화 단계&lt;/b&gt;에서 사용됩니다.&lt;/li&gt;
&lt;li&gt;TurboFan은 최적화된 바&lt;b&gt;이트코드를 받아들여 최적화된 기계어 코드로 컴파일&lt;/b&gt;합니다.&lt;/li&gt;
&lt;li&gt;&lt;span&gt;TurboFan&lt;/span&gt;은&lt;span&gt; &lt;/span&gt;자주&lt;span&gt; &lt;/span&gt;사용되는&lt;span&gt; &lt;/span&gt;코드&lt;span&gt; &lt;/span&gt;블록을&lt;span&gt; &lt;/span&gt;추적하고&lt;span&gt;, &lt;/span&gt;이를&lt;span&gt; &lt;/span&gt;기반으로&lt;span&gt; &lt;/span&gt;최적화를&lt;span&gt; &lt;/span&gt;수행합니다&lt;span&gt;. &lt;/span&gt;이를&lt;span&gt; &lt;/span&gt;통해&lt;span&gt; &lt;/span&gt;성능을&lt;span&gt; 향상시키고, &lt;/span&gt;실행&lt;span&gt; &lt;/span&gt;시간을&lt;span&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;b&gt;히든 클래스(Hidden Class)&lt;/b&gt;나 &lt;b&gt;인라인 캐싱(Inline Caching)&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;b&gt;비슷한 것들끼리 분류해 놓고&lt;/b&gt; 가져다 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인라인 캐싱 - 자주 사용되는 코드가 만약 excute()와 같은 함수의 호출 부라면 이걸 function excute () {... }와 같이&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 실행(Execution):&lt;/h4&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;코드는&amp;nbsp;CPU에서&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;코드의&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;것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;5. 가비지 컬렉션(Garbage Collection)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&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;수행됩니다.&lt;br /&gt;V8&amp;nbsp;엔진은&amp;nbsp;가비지&amp;nbsp;컬렉션을&amp;nbsp;효율적으로&amp;nbsp;수행하여&amp;nbsp;메모리&amp;nbsp;누수를&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;640&quot; data-origin-height=&quot;480&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btOoST/btsGwOxo2yv/nLhsku1umD6sGmYWslBN3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btOoST/btsGwOxo2yv/nLhsku1umD6sGmYWslBN3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btOoST/btsGwOxo2yv/nLhsku1umD6sGmYWslBN3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtOoST%2FbtsGwOxo2yv%2FnLhsku1umD6sGmYWslBN3k%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;579&quot; height=&quot;434&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;480&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;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;그렇다면 어떻게 코드를 짜야할까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 id=&quot;hidden-classes&quot; style=&quot;color: #313130; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Hidden Classes&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #313130; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Javascript는 컴파일시에 사용하는 타입정보에 대해 제한적이다.&lt;/li&gt;
&lt;li&gt;Javascript는 런타임시에 데이터 타입을 변경할 수 있다.&lt;/li&gt;
&lt;li&gt;V8은 런타임시에 객체 처리를 위해 내부적으로 hidden class를 만들어서 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1712839431014&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Point(x, y) {
  this.x = x;
  this.y = y;
}

var p1 = new Point(11, 22);
var p2 = new Point(33, 44);
// 여기에서 p1과 p2는 hidden class를 공유합니다.
p2.z = 55;
// 경고! p1과 p2는 이제 다른 hidden class를 갖습니다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 id=&quot;결론&quot; style=&quot;color: #313130; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;결론&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; color: #313130; text-align: start;&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;b&gt;항상 같은 순서로 멤버를 초기화&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 id=&quot;numbers&quot; style=&quot;color: #313130; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Numbers&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #313130; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;V8은 데이터 타입 변환시 값을 효율적으로 나타내는 태그 사용&lt;/li&gt;
&lt;li&gt;사용자가 사용하는 값을 통해서 number타입 추론&lt;/li&gt;
&lt;li&gt;데이터 타입은 동적으로 변할 수 있기 때문에, 효율적으로 값을 나타내는 태그 사용&lt;/li&gt;
&lt;li&gt;number타입을 지속적으로 쓰는 것이 중요&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1712839469130&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var i = 42;  // 31비트 부호있는 정수입니다.
var j = 4.2;  // 이 값은 double 타입의 부동 소수점 숫자 데이터입니다.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote style=&quot;color: #313130; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;h4 id=&quot;결론-1&quot; data-ke-size=&quot;size20&quot;&gt;결론&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;31비트 부호있는 정수를 사용&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 id=&quot;normal-arrays&quot; style=&quot;color: #313130; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Normal Arrays&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #313130; text-align: start;&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;Fast Elements : 키 값이 순서대로 채워진 경우 사용되는 선형 저장소&lt;/li&gt;
&lt;li&gt;Dictionary Elements : 위 경우가 아닐 때 사용하는 해쉬 테이블 저장소&lt;/li&gt;
&lt;/ul&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;pre id=&quot;code_1712839552402&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  a = new Array();
  for (var b = 0; b &amp;lt; 10; b++) {
    a[0] |= b;  // 안 좋아요!
  }
  //vs.
  a = new Array();
  a[0] = 0;
  for (var b = 0; b &amp;lt; 10; b++) {
    a[0] |= b;  // 훨씬 좋습니다. 2배 더 빨라요.
  }&lt;/code&gt;&lt;/pre&gt;
&lt;h4 id=&quot;결론-2&quot; style=&quot;color: #313130; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;결론&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; color: #313130; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;인덱스 0부터 시작하는 연속키 사용&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;배열 선언시 최대사이즈를 할당하지 말고 ( &amp;gt; 64K 원소), 사용하면서 크기를 늘려간다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;숫자 배열의 요소를 삭제하지 않는다&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;초기화 안한 요소는 호출하지 않는다 (아래 코드 참조)&lt;/b&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;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;Reference&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;&lt;a href=&quot;https://evan-moon.github.io/2019/06/28/v8-analysis/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://evan-moon.github.io/2019/06/28/v8-analysis/&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712839228069&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;V8 엔진은 어떻게 내 코드를 실행하는 걸까?&quot; data-og-description=&quot;이번 포스팅에서는 구글의 V8 엔진이 어떤 방식으로 자바스크립트를 해석하고 실행하는지 살펴 보는지에 대해 포스팅하려고 한다. 은 로 작성되었지만 필자의 메인 언어가 이 아니기도 하고, 워&quot; data-og-host=&quot;evan-moon.github.io&quot; data-og-source-url=&quot;https://evan-moon.github.io/2019/06/28/v8-analysis/&quot; data-og-url=&quot;https://evan-moon.github.io/2019/06/28/v8-analysis/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bdbjrI/hyVPQMKu8a/M4PaEBU2v1ALKZUUMAbhfk/img.png?width=1000&amp;amp;height=500&amp;amp;face=0_0_1000_500,https://scrap.kakaocdn.net/dn/qRjv4/hyVPPUBbjI/j1D9U7VYUMeZn8IyMSiuHk/img.png?width=1000&amp;amp;height=500&amp;amp;face=0_0_1000_500,https://scrap.kakaocdn.net/dn/pT8eM/hyVMNRHvO4/sNMqfxfTf8iIbSEvNkKt9k/img.png?width=640&amp;amp;height=480&amp;amp;face=0_0_640_480&quot;&gt;&lt;a href=&quot;https://evan-moon.github.io/2019/06/28/v8-analysis/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://evan-moon.github.io/2019/06/28/v8-analysis/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bdbjrI/hyVPQMKu8a/M4PaEBU2v1ALKZUUMAbhfk/img.png?width=1000&amp;amp;height=500&amp;amp;face=0_0_1000_500,https://scrap.kakaocdn.net/dn/qRjv4/hyVPPUBbjI/j1D9U7VYUMeZn8IyMSiuHk/img.png?width=1000&amp;amp;height=500&amp;amp;face=0_0_1000_500,https://scrap.kakaocdn.net/dn/pT8eM/hyVMNRHvO4/sNMqfxfTf8iIbSEvNkKt9k/img.png?width=640&amp;amp;height=480&amp;amp;face=0_0_640_480');&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;V8 엔진은 어떻게 내 코드를 실행하는 걸까?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 구글의 V8 엔진이 어떤 방식으로 자바스크립트를 해석하고 실행하는지 살펴 보는지에 대해 포스팅하려고 한다. 은 로 작성되었지만 필자의 메인 언어가 이 아니기도 하고, 워&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;evan-moon.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@ainochi95/20mV8-%EC%97%94%EC%A7%84%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%84-%EA%B0%9C%EC%84%A0%ED%96%88%EC%9D%84%EA%B9%8C&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://velog.io/@ainochi95/20mV8-%EC%97%94%EC%A7%84%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%84-%EA%B0%9C%EC%84%A0%ED%96%88%EC%9D%84%EA%B9%8C&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712839234863&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;V8 엔진은 무엇을 개선했을까?&quot; data-og-description=&quot;2012년 구글 I/O 2012에서 발표한 JS의 성능에 관련된 발표가 있다&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@ainochi95/20mV8-%EC%97%94%EC%A7%84%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%84-%EA%B0%9C%EC%84%A0%ED%96%88%EC%9D%84%EA%B9%8C&quot; data-og-url=&quot;https://velog.io/@ainochi95/20mV8-엔진은-무엇을-개선했을까&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/jtK5z/hyVPRES4OE/YCDGhk8NfDYTaQckkOkz80/img.png?width=1035&amp;amp;height=547&amp;amp;face=0_0_1035_547,https://scrap.kakaocdn.net/dn/hIW32/hyVMRmdaBI/u6ez6514iM2jP9kXbOmUa1/img.png?width=1035&amp;amp;height=547&amp;amp;face=0_0_1035_547,https://scrap.kakaocdn.net/dn/PZ9Cp/hyVMQU9L1R/sm5QkO41GNY85Qw5AgEQn0/img.png?width=1035&amp;amp;height=547&amp;amp;face=0_0_1035_547&quot;&gt;&lt;a href=&quot;https://velog.io/@ainochi95/20mV8-%EC%97%94%EC%A7%84%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%84-%EA%B0%9C%EC%84%A0%ED%96%88%EC%9D%84%EA%B9%8C&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@ainochi95/20mV8-%EC%97%94%EC%A7%84%EC%9D%80-%EB%AC%B4%EC%97%87%EC%9D%84-%EA%B0%9C%EC%84%A0%ED%96%88%EC%9D%84%EA%B9%8C&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/jtK5z/hyVPRES4OE/YCDGhk8NfDYTaQckkOkz80/img.png?width=1035&amp;amp;height=547&amp;amp;face=0_0_1035_547,https://scrap.kakaocdn.net/dn/hIW32/hyVMRmdaBI/u6ez6514iM2jP9kXbOmUa1/img.png?width=1035&amp;amp;height=547&amp;amp;face=0_0_1035_547,https://scrap.kakaocdn.net/dn/PZ9Cp/hyVMQU9L1R/sm5QkO41GNY85Qw5AgEQn0/img.png?width=1035&amp;amp;height=547&amp;amp;face=0_0_1035_547');&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;V8 엔진은 무엇을 개선했을까?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;2012년 구글 I/O 2012에서 발표한 JS의 성능에 관련된 발표가 있다&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://engineering.linecorp.com/ko/blog/v8-hidden-class&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://engineering.linecorp.com/ko/blog/v8-hidden-class&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712839234480&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;V8의 히든 클래스 이야기&quot; data-og-description=&quot;자바스크립트가 되어 그 기분을 헤아릴 수 있다면 안녕하세요? LINE Fukuoka의 프론트엔드 엔지니어 Yonehara입니다. 저는 프론트엔드 개발자로서 아직 웹 브라우저나 자바스크립트의 기분을 헤아려&quot; data-og-host=&quot;engineering.linecorp.com&quot; data-og-source-url=&quot;https://engineering.linecorp.com/ko/blog/v8-hidden-class&quot; data-og-url=&quot;https://engineering.linecorp.com/ko/blog/v8-hidden-class&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/duLD3F/hyVPRSqemx/bPK0DFkOkR80k7fX5HOPH1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/c1bo68/hyVMRGwkac/kfzYZ3lxW7v7okhOoGTAqK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cIg08j/hyVPT3LNSp/D2I4eYT8lx9uOKpG4AxBXK/img.png?width=680&amp;amp;height=688&amp;amp;face=0_0_680_688&quot;&gt;&lt;a href=&quot;https://engineering.linecorp.com/ko/blog/v8-hidden-class&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://engineering.linecorp.com/ko/blog/v8-hidden-class&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/duLD3F/hyVPRSqemx/bPK0DFkOkR80k7fX5HOPH1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/c1bo68/hyVMRGwkac/kfzYZ3lxW7v7okhOoGTAqK/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/cIg08j/hyVPT3LNSp/D2I4eYT8lx9uOKpG4AxBXK/img.png?width=680&amp;amp;height=688&amp;amp;face=0_0_680_688');&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;V8의 히든 클래스 이야기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자바스크립트가 되어 그 기분을 헤아릴 수 있다면 안녕하세요? LINE Fukuoka의 프론트엔드 엔지니어 Yonehara입니다. 저는 프론트엔드 개발자로서 아직 웹 브라우저나 자바스크립트의 기분을 헤아려&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;engineering.linecorp.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;&lt;a href=&quot;https://joshua1988.github.io/web-development/web-perf/perf-tip-javascript-in-v8/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://joshua1988.github.io/web-development/web-perf/perf-tip-javascript-in-v8/&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>javascript</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/221</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%99%80-V8#entry221comment</comments>
      <pubDate>Thu, 11 Apr 2024 21:51:05 +0900</pubDate>
    </item>
    <item>
      <title>애자일(Agile) 이란?</title>
      <link>https://hmk1022.tistory.com/entry/%EC%95%A0%EC%9E%90%EC%9D%BCAgile-%EC%9D%B4%EB%9E%80</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Agile&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;처음부터 끝까지 계획을 수립하고 개발하는 폭포수(waterfall) 방법론과는 달리&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;size16&quot;&gt;-&amp;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;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;&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;(ex. sprint)하여 하나의 큰 프로젝트를 나가는 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 핵심은 &lt;b&gt;유연성과 의사소통 그리고 동료와의 협업&lt;/b&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;애자일을 계승한 방법론 스크럼(scrum)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애자일 방법론에는 스크럼, 칸반, XP, LSD 등이 있지만 필자는 scrum만 경험해봤고,&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;br /&gt;스프린트(sprint)라고 하는 단기 작업 븡록을 통해 프로젝트를 진행하며&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&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;스프린트 기간은 보통 1~4주 정도로 진행합니다. (필자는 보통 1~2주의 스프린트를 경험)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;p data-ke-size=&quot;size18&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;필자의 경우는 P1 &amp;gt; P5 등의 우선순위를 매겨가며 우선순위를 부여했다.&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;457&quot; data-origin-height=&quot;137&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzfsk8/btsGqu7Kwvo/WQpOGKN0bFp8BFqNIRARZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzfsk8/btsGqu7Kwvo/WQpOGKN0bFp8BFqNIRARZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzfsk8/btsGqu7Kwvo/WQpOGKN0bFp8BFqNIRARZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbzfsk8%2FbtsGqu7Kwvo%2FWQpOGKN0bFp8BFqNIRARZ0%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;457&quot; height=&quot;137&quot; data-origin-width=&quot;457&quot; data-origin-height=&quot;137&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;p data-ke-size=&quot;size18&quot;&gt;- 개발 주기는 1~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;너무 짧으면(분석/설계/개발/테스트) 할 수 있는 시간이 부족하고,&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;754&quot; data-origin-height=&quot;670&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4D2jI/btsGqkK2cOu/WnDA9woeI5x0u0tjyuFGqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4D2jI/btsGqkK2cOu/WnDA9woeI5x0u0tjyuFGqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4D2jI/btsGqkK2cOu/WnDA9woeI5x0u0tjyuFGqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4D2jI%2FbtsGqkK2cOu%2FWnDA9woeI5x0u0tjyuFGqK%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;614&quot; height=&quot;546&quot; data-origin-width=&quot;754&quot; data-origin-height=&quot;670&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&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;/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;해당 주기의 Goal을 작성하지 않으면 목적을 잃은 기능이 될 수있음,&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;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IXElO/btsGtkigYcr/9Xk06mJnpBqXgnKj4DBJ11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IXElO/btsGtkigYcr/9Xk06mJnpBqXgnKj4DBJ11/img.png&quot; data-is-animation=&quot;false&quot; data-origin-height=&quot;660&quot; data-origin-width=&quot;1408&quot; style=&quot;width: 62.127%; margin-right: 10px;&quot; data-widthpercent=&quot;62.86&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IXElO/btsGtkigYcr/9Xk06mJnpBqXgnKj4DBJ11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIXElO%2FbtsGtkigYcr%2F9Xk06mJnpBqXgnKj4DBJ11%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;1408&quot; height=&quot;660&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAGkbp/btsGqliV7Ke/2sWMzGoTKAskrbnWix10O0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAGkbp/btsGqliV7Ke/2sWMzGoTKAskrbnWix10O0/img.png&quot; data-origin-width=&quot;537&quot; data-origin-height=&quot;426&quot; data-is-animation=&quot;false&quot; style=&quot;width: 36.7102%;&quot; data-widthpercent=&quot;37.14&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAGkbp/btsGqliV7Ke/2sWMzGoTKAskrbnWix10O0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAGkbp%2FbtsGqliV7Ke%2F2sWMzGoTKAskrbnWix10O0%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;537&quot; height=&quot;426&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 매일 15분 정도의 Scrum 회의를 가져라&lt;/p&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;span style=&quot;color: #333333; text-align: start;&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;/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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;739&quot; data-origin-height=&quot;885&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cilI0X/btsGpTUKHhl/5oajShrFHflsXZGKKxO0Tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cilI0X/btsGpTUKHhl/5oajShrFHflsXZGKKxO0Tk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cilI0X/btsGpTUKHhl/5oajShrFHflsXZGKKxO0Tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcilI0X%2FbtsGpTUKHhl%2F5oajShrFHflsXZGKKxO0Tk%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;724&quot; height=&quot;867&quot; data-origin-width=&quot;739&quot; data-origin-height=&quot;885&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;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&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;&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;자신의 task보다 주변 이슈가 더 급하다면 유동적으로 지원하거나 도와줘야한다.&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;&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;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&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;Scrum의 추구 가치&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li id=&quot;365e&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;&lt;b&gt;용기 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;옳은 일을 할 수 있도록 팀원간 갈등과 도전을 위한 용기를 가져라!&lt;br /&gt;(설명 : 해당 기능이 이해가 안되거나 문제가 있다면 말할 수 있어야 하고, 더 일을 잘 할 수 있는 환경을 요구하고, 자신의 신념을 설득 시켜야 한다. 또한 도전적으로 시도해보는 용기와 완료 할 수 없는 업무량이라고 모두 말 할 수 있어야 한다.)&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li id=&quot;076c&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;&lt;b&gt;집중 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;할 일을 하라. 모든 노력과 기술은 성공을 위해 집중하고, 그 외는 걱정(신경쓰지) 마라!&lt;br /&gt;(설명 : 한번에 하나의 일부터 마무리하고, 업무에 집중 할 수 있도록 불필요한 회의 참석은 지양하며, 루틴한 반복 작업은 제거 하거나 자동화해야 한다.)&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li id=&quot;e810&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;&lt;b&gt;약속(헌신/책임) :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;팀의 목표 달성을 위해 개개인이 공약한 목표 달성을 위해 팀에 헌신하며, 이를 달성 위해 필요한 모든 권한을 부여하라!&lt;br /&gt;(설명 : 개인보다는 팀성과 달성이 우선이고, Value 있는 SW를 개발 할 수 있게 최대한 지원과 권한이 필요하다.)&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li id=&quot;e12b&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;&lt;b&gt;존중 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;경력과 경험이 사람을 만든다. 팀원들을 존중하라!&lt;br /&gt;(설명 : 개개인별로 장단점이 있고, 그 사람이 그렇게 할 수 밖에 없는 이유가 있을것이다.)&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li id=&quot;305b&quot; style=&quot;list-style-type: disc; color: #242424;&quot; data-selectable-paragraph=&quot;&quot;&gt;&lt;b&gt;투명성/개방성 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;프로젝트에 대한 모든 내용을 투명하게 공개하라!&lt;br /&gt;(설명 : 제품백로그, 스크럼 회의, 스프린트 리뷰를 통해 공유되며, 자신에게 불리해도 숨기지 않고 도움을 요청한다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&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;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;b&gt;Reference&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;&lt;a href=&quot;https://medium.com/dtevangelist/scrum-dfc6523a3604&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://medium.com/dtevangelist/scrum-dfc6523a3604&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <category>product</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/220</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%95%A0%EC%9E%90%EC%9D%BCAgile-%EC%9D%B4%EB%9E%80#entry220comment</comments>
      <pubDate>Sun, 7 Apr 2024 20:57:56 +0900</pubDate>
    </item>
    <item>
      <title>프로세스 스케줄링 알고리즘</title>
      <link>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
      <description>&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 할당을 위한 프로세스 스케줄링 알고리즘의 종류는 아래와 같다.&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;1. 선입 선처리 스케줄링(FIFO)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;준비 큐에 삽입된 &lt;b&gt;순서대로 CPU를 할당&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;size18&quot;&gt;2. 최단 작업 우선 스케줄링(Shortest Job First)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실행 시간이 가장 짧은 프로세스부터 CPU를 할당&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 라운드 로빈 스케줄링(Round Robin)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;준비 큐에 삽입된 순서대로 CPU를 할당&lt;/b&gt;하지만, &lt;b&gt;정해진 시간(타임 슬라이스)만큼만 할당&lt;/b&gt;해주는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정해진&lt;span&gt; &lt;/span&gt;시간동안&lt;span&gt; &lt;/span&gt;전부&lt;span&gt; &lt;/span&gt;실행되지&lt;span&gt; &lt;/span&gt;못했다면&lt;span&gt;, &lt;/span&gt;맨&lt;span&gt; &lt;/span&gt;마지막&lt;span&gt; &lt;/span&gt;순서로&lt;span&gt; &lt;/span&gt;돌아가서&lt;span&gt; &lt;/span&gt;다시&lt;span&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-origin-width=&quot;2000&quot; data-origin-height=&quot;1117&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qyqOn/btsGmfu49Hy/XGHvXD6MT1RDx89YAn8Vsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qyqOn/btsGmfu49Hy/XGHvXD6MT1RDx89YAn8Vsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qyqOn/btsGmfu49Hy/XGHvXD6MT1RDx89YAn8Vsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqyqOn%2FbtsGmfu49Hy%2FXGHvXD6MT1RDx89YAn8Vsk%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;751&quot; height=&quot;419&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1117&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;p data-ke-size=&quot;size18&quot;&gt;4. 최소 잔여 시간 우선 스케줄링&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 정해진 시간만큼 CPU를 할당하되, &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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;5. 우선순위 스케줄링&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;- &lt;b&gt;우선순위가 낮은 프로세스는 무한정 실행되지 못하는 기아(Starvation)현상&lt;/b&gt;이 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 기아 현상 방지를 위해 오래 기다린 프로세스의 우선순위를 점차 높이는 에이징(Aging)기법을 사용한다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;6. 다단계 큐 스케줄링(Multilevel Queue Scheduling)&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;- 우선순위가 가장 높은 큐가 비어 있으면, 그 다음 우선순위 큐를 처리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;우선&lt;span&gt; &lt;/span&gt;순위가&lt;span&gt; &lt;/span&gt;낮은&lt;span&gt; &lt;/span&gt;프로세스는&lt;span&gt; &lt;/span&gt;기아&lt;span&gt; &lt;/span&gt;현상&lt;/b&gt;이&lt;span&gt; &lt;/span&gt;발생할&lt;span&gt; &lt;/span&gt;수&lt;span&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-origin-width=&quot;2000&quot; data-origin-height=&quot;995&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dIH0X9/btsGmuZRBgb/Odhi86lHKfcBKXzzsvkc6k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dIH0X9/btsGmuZRBgb/Odhi86lHKfcBKXzzsvkc6k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dIH0X9/btsGmuZRBgb/Odhi86lHKfcBKXzzsvkc6k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdIH0X9%2FbtsGmuZRBgb%2FOdhi86lHKfcBKXzzsvkc6k%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;2000&quot; height=&quot;995&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;995&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;p data-ke-size=&quot;size18&quot;&gt;7&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;- &lt;b&gt;우선순위&lt;/b&gt;가 가장 높은 큐부터 처리를 하되, 일정 시간(타임 슬라이스)동안 못 끝낸 경우 &lt;b&gt;그 다음 우선 순위 큐&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉&lt;span&gt;, CPU &lt;/span&gt;사용&lt;span&gt; &lt;/span&gt;시간이&lt;span&gt; &lt;/span&gt;긴&lt;span&gt; &lt;b&gt;CPU &lt;/b&gt;&lt;/span&gt;&lt;b&gt;집중&lt;/b&gt;&lt;span&gt;&lt;b&gt;(CPU Bound) &lt;/b&gt;&lt;/span&gt;&lt;b&gt;프로세스는&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;우선&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;순위가&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;상대적으로&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;낮아지고&lt;/b&gt;&lt;span&gt;, CPU &lt;/span&gt;사용&lt;span&gt; &lt;/span&gt;시간이&lt;span&gt; &lt;/span&gt;짧고&lt;span&gt; &lt;/span&gt;입출력&lt;span&gt; &lt;/span&gt;작업이&lt;span&gt; &lt;/span&gt;많은&lt;span&gt; &lt;/span&gt;&lt;b&gt;입출력&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;집중&lt;/b&gt;&lt;span&gt;&lt;b&gt;(I/O Bound) &lt;/b&gt;&lt;/span&gt;&lt;b&gt;프로세스는&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;우선&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;순위가&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;상대적으로&lt;/b&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;b&gt;높아진다&lt;/b&gt;&lt;span&gt;&lt;b&gt;.&lt;/b&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;2000&quot; data-origin-height=&quot;996&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOJ1Op/btsGjQp7aVw/7KgIIkOQKAlS2ykAMmuzz0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOJ1Op/btsGjQp7aVw/7KgIIkOQKAlS2ykAMmuzz0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOJ1Op/btsGjQp7aVw/7KgIIkOQKAlS2ykAMmuzz0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOJ1Op%2FbtsGjQp7aVw%2F7KgIIkOQKAlS2ykAMmuzz0%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;2000&quot; height=&quot;996&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;996&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1013&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUHwmG/btsGjZ78IiN/D8gwudRg5qZZqy3b0X5Ozk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUHwmG/btsGjZ78IiN/D8gwudRg5qZZqy3b0X5Ozk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUHwmG/btsGjZ78IiN/D8gwudRg5qZZqy3b0X5Ozk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUHwmG%2FbtsGjZ78IiN%2FD8gwudRg5qZZqy3b0X5Ozk%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;2000&quot; height=&quot;1013&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1013&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1097&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4W3kb/btsGmVbPjcS/uGUffIqQZ335gQQE8IRfN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4W3kb/btsGmVbPjcS/uGUffIqQZ335gQQE8IRfN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4W3kb/btsGmVbPjcS/uGUffIqQZ335gQQE8IRfN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4W3kb%2FbtsGmVbPjcS%2FuGUffIqQZ335gQQE8IRfN0%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;2000&quot; height=&quot;1097&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1097&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;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;b&gt;Reference&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=isj4sZhoxjk&amp;amp;list=PLYH7OjNUOWLUz15j4Q9M6INxK5J3-59GC&amp;amp;index=3&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=isj4sZhoxjk&amp;amp;list=PLYH7OjNUOWLUz15j4Q9M6INxK5J3-59GC&amp;amp;index=3&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <category>cs</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/219</guid>
      <comments>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%8A%A4%EC%BC%80%EC%A4%84%EB%A7%81-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98#entry219comment</comments>
      <pubDate>Wed, 3 Apr 2024 22:28:16 +0900</pubDate>
    </item>
    <item>
      <title>좋은 UX란 무엇일까?(feat. 프론트엔드 개발자)</title>
      <link>https://hmk1022.tistory.com/entry/%EC%A2%8B%EC%9D%80-UX%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8Cfeat-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;UX는 사용자 경험(User Experience)다.&lt;/p&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;토스나 카뱅같은 서비스가 아닌 다른 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;&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;나는 이런 꼭 필요하고 자주 이용하는 메뉴임에도 이런 UX를 만나면 피가 거꾸로 솟는다....&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;&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;353&quot; data-origin-height=&quot;410&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GZMX6/btsGgDoQiSk/gRHzbIrbtXGuWKbFzMjyNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GZMX6/btsGgDoQiSk/gRHzbIrbtXGuWKbFzMjyNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GZMX6/btsGgDoQiSk/gRHzbIrbtXGuWKbFzMjyNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGZMX6%2FbtsGgDoQiSk%2FgRHzbIrbtXGuWKbFzMjyNK%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;290&quot; height=&quot;337&quot; data-origin-width=&quot;353&quot; data-origin-height=&quot;410&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;좋은 UX란 무엇일까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 사용자 경험(UX)은 사용자가 &lt;b&gt;제품 또는 서비스를 사용할 때 느끼는 전반적인 만족과 편의성&lt;/b&gt;을 의미합니다. 이는 디자인, 상호 작용, 성능 및 사용자의 감정적 반응을 포함하는 다양한 요소들의 조합으로 결정됩니다. 몇 가지 주요 특징은 다음과 같습니다.&lt;br /&gt;&lt;br /&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;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;유용성&lt;/b&gt;: 제품이나 서비스가 &lt;b&gt;사용자의 실제 필요를 충족&lt;/b&gt;하는지 여부. 이는 사용자가 그들의 목표를 달성하는 데 도움이 되는 기능과 정보를 제공하는 것을 의미합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;가시성&lt;/b&gt;: 사용자가 &lt;b&gt;현재 위치, 가능한 작업 및 다음 단계를 명확히 이해할 수 있는지 여부&lt;/b&gt;. 이는 일관된 디자인 및 명시적인 내비게이션을 통해 달성됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;효율성&lt;/b&gt;: 사용자가 &lt;b&gt;목표를 달성하는 데 드는 시간과 노력을 최소화하는 것&lt;/b&gt;. 단축키, 자동 완성 및 예측 기능과 같은 기능이 이에 기여합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;참여도&lt;/b&gt;: 사용자가 제품 또는 서비스와 상호 작용하는 과정에서 느끼는 &lt;b&gt;긍정적인 감정 및 연결.&lt;/b&gt; 이는 사용자의 신뢰를 구축하고 충성도를 높이는 데 중요합니다.&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;접근성&lt;/b&gt;&lt;span&gt;: &lt;/span&gt;모든&lt;span&gt; &lt;/span&gt;사용자가&lt;span&gt; &lt;/span&gt;&lt;b&gt;제품이나&lt;span&gt; &lt;/span&gt;서비스에&lt;span&gt; &lt;/span&gt;동등하게&lt;span&gt; &lt;/span&gt;접근할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있는지&lt;span&gt; &lt;/span&gt;여부&lt;span&gt;. &lt;/span&gt;&lt;/b&gt;장애인을&lt;span&gt; &lt;/span&gt;고려한&lt;span&gt; &lt;/span&gt;디자인&lt;span&gt;, &lt;/span&gt;다양한&lt;span&gt; &lt;/span&gt;디바이스&lt;span&gt; &lt;/span&gt;및&lt;span&gt; &lt;/span&gt;브라우저&lt;span&gt; &lt;/span&gt;호환성&lt;span&gt; &lt;/span&gt;등이&lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;좋은 UX에 대해 검색하면 흔히 알고 있다시피 위와 같은 내용이 나옵니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;프런트엔드 개발자 입장에서, 이를 더 간단하게 함축해 보면 저는 아래의 4가지 요소가 고려된 서비스가 좋은 UX라고 생각이 듭니다.&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&gt;1. 간편함 - 말해 뭐 해&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;2. 사용자의 실수를 예상하여 막아줌 - 감동&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;3. 디테일 - 감동&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;4. 성능 - 우아한 백조의 쉴 새 없이 움직이는 물장구&lt;br /&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;랜딩 페이지 로딩 소요시간 부드러운 UX, sementic, 웹접근성, LCP, INP, Light house score 등등..&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;프런트엔드 개발자가 UI/UX를 알아야 할까?&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;&quot;프런트엔드 개발자는 기획, 디자인을 보고 충실하게 구현만 하면 된다&quot;라고 생각했다.&lt;/p&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;나는 단연코 해당화면을 구현하는 프런트엔드 개발자라고 생각한다.(이것은 소규모 스타트업 FE개발자인 필자의 경험)&lt;/p&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이에 더해, 요즘 FE개발자 채용공고에 UX에 대한 이해를 자격, 우대 조건으로 써놓는 회사가 많아졌다.&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&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;사실 UX에 대해 전문적인 지식도 없고, UX에 대한 정석적인 이론들은 잘 알지 못한다.&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;764&quot; data-origin-height=&quot;386&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QHzHH/btsGd1ESYHC/xt0DpOMhPiTKE3KWVibr71/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QHzHH/btsGd1ESYHC/xt0DpOMhPiTKE3KWVibr71/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QHzHH/btsGd1ESYHC/xt0DpOMhPiTKE3KWVibr71/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQHzHH%2FbtsGd1ESYHC%2Fxt0DpOMhPiTKE3KWVibr71%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;663&quot; height=&quot;335&quot; data-origin-width=&quot;764&quot; data-origin-height=&quot;386&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 data-ke-size=&quot;size16&quot;&gt;2. 경험과 아는 지식으로 디자이너에게 제안 및 빠뜨린 부분에 대해 &quot;정중하게&quot; 피드백&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 직접 서비스의 유저가 되어 실제 페인포인트를 제품에 녹인다.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에서 말했다시피 필자는 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;b&gt;구매대행 업자를 위한&lt;/b&gt; 이커머스 관련&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;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;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&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/cNXDVs/btsGeANrVWi/cp8FA78FuKvOV1wJCsnz50/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNXDVs/btsGeANrVWi/cp8FA78FuKvOV1wJCsnz50/img.jpg&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;324&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.2475%; margin-right: 10px;&quot; data-widthpercent=&quot;48.82&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNXDVs/btsGeANrVWi/cp8FA78FuKvOV1wJCsnz50/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNXDVs%2FbtsGeANrVWi%2Fcp8FA78FuKvOV1wJCsnz50%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;800&quot; height=&quot;324&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VJUJK/btsGfyamml2/pwG94Aqfh3aSlMcWeZlaR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VJUJK/btsGfyamml2/pwG94Aqfh3aSlMcWeZlaR0/img.png&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;309&quot; data-is-animation=&quot;false&quot; style=&quot;width: 50.5897%;&quot; data-widthpercent=&quot;51.18&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VJUJK/btsGfyamml2/pwG94Aqfh3aSlMcWeZlaR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVJUJK%2FbtsGfyamml2%2FpwG94Aqfh3aSlMcWeZlaR0%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;800&quot; height=&quot;309&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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1928&quot; data-origin-height=&quot;920&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwTQwC/btsGdrcRIAI/xzp8joc2i6Tw7CUbJ1e8c0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwTQwC/btsGdrcRIAI/xzp8joc2i6Tw7CUbJ1e8c0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwTQwC/btsGdrcRIAI/xzp8joc2i6Tw7CUbJ1e8c0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwTQwC%2FbtsGdrcRIAI%2Fxzp8joc2i6Tw7CUbJ1e8c0%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;1928&quot; height=&quot;920&quot; data-origin-width=&quot;1928&quot; data-origin-height=&quot;920&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c67opb/btsGfKuZ2K9/pkrxs2SF5BjdA5rJrkgtNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c67opb/btsGfKuZ2K9/pkrxs2SF5BjdA5rJrkgtNk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c67opb/btsGfKuZ2K9/pkrxs2SF5BjdA5rJrkgtNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc67opb%2FbtsGfKuZ2K9%2Fpkrxs2SF5BjdA5rJrkgtNk%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;1248&quot; height=&quot;374&quot; data-origin-width=&quot;1248&quot; data-origin-height=&quot;374&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;그 결과, 적어도 이 분야의 타업체들에 비해 더 좋은 UX를 제공하는 서비스를 만들었다고 자신한다.(이 정도 자신감은 있어도 되지 않습니까!?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. 경험과 아는 지식으로 디자이너에게 제안 및 빠뜨린 부분에 대해 &quot;정중하게&quot; 피드백&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 이 부분에 대해선 &quot;정중하게&quot;라는 키워드도 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직군마다 역할이 있고 사람마다 성향이 다르기 때문에 소프트한 커뮤니케이션이 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;447&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uZrMj/btsGff9QOql/xWZSqKQRAkOt6PWb0P9B6k/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uZrMj/btsGff9QOql/xWZSqKQRAkOt6PWb0P9B6k/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uZrMj/btsGff9QOql/xWZSqKQRAkOt6PWb0P9B6k/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuZrMj%2FbtsGff9QOql%2FxWZSqKQRAkOt6PWb0P9B6k%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;636&quot; height=&quot;395&quot; data-origin-width=&quot;720&quot; data-origin-height=&quot;447&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;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상대방에 대한 호감도 및 커뮤니케이션 빈도 하락 -&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수동적인 업무 소통 -&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제품에 &lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;대한 의사소통 및 좋은 아이디어 창출 기회 하락 -&amp;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;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;&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&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/btxw7N/btsGfxJiWlm/NWjUv1MYjKewhT8XoYKSM0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btxw7N/btsGfxJiWlm/NWjUv1MYjKewhT8XoYKSM0/img.jpg&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;482&quot; data-is-animation=&quot;false&quot; style=&quot;width: 30.0385%; margin-right: 10px;&quot; data-widthpercent=&quot;30.39&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btxw7N/btsGfxJiWlm/NWjUv1MYjKewhT8XoYKSM0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbtxw7N%2FbtsGfxJiWlm%2FNWjUv1MYjKewhT8XoYKSM0%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;300&quot; height=&quot;482&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wJAoc/btsGfvY0Of0/7jYokY5fLSyIh4q3EmvWq1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wJAoc/btsGfvY0Of0/7jYokY5fLSyIh4q3EmvWq1/img.jpg&quot; data-origin-width=&quot;268&quot; data-origin-height=&quot;188&quot; data-is-animation=&quot;false&quot; style=&quot;width: 68.7987%;&quot; data-widthpercent=&quot;69.61&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wJAoc/btsGfvY0Of0/7jYokY5fLSyIh4q3EmvWq1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwJAoc%2FbtsGfvY0Of0%2F7jYokY5fLSyIh4q3EmvWq1%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;268&quot; height=&quot;188&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;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;PM -&amp;gt; 디자이너 -&amp;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;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;Untitled (3).png&quot; data-origin-width=&quot;1716&quot; data-origin-height=&quot;1134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yYgKn/btsGgBkiiq7/1UreE9c1xrcLmJnCSkXBr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yYgKn/btsGgBkiiq7/1UreE9c1xrcLmJnCSkXBr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yYgKn/btsGgBkiiq7/1UreE9c1xrcLmJnCSkXBr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyYgKn%2FbtsGgBkiiq7%2F1UreE9c1xrcLmJnCSkXBr1%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;1716&quot; height=&quot;1134&quot; data-filename=&quot;Untitled (3).png&quot; data-origin-width=&quot;1716&quot; data-origin-height=&quot;1134&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Untitled (2).png&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/31OiO/btsGdqE1jCy/VXMTXKRG1l1AA5IJ5tA3kK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/31OiO/btsGdqE1jCy/VXMTXKRG1l1AA5IJ5tA3kK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/31OiO/btsGdqE1jCy/VXMTXKRG1l1AA5IJ5tA3kK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F31OiO%2FbtsGdqE1jCy%2FVXMTXKRG1l1AA5IJ5tA3kK%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;1426&quot; height=&quot;690&quot; data-filename=&quot;Untitled (2).png&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;/figure&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/bDDOiU/btsGeRBoOAg/K0Vev3tVNcksr1QdzCNdV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDDOiU/btsGeRBoOAg/K0Vev3tVNcksr1QdzCNdV0/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;848&quot; data-origin-height=&quot;1230&quot; data-filename=&quot;Untitled (1).png&quot; style=&quot;width: 41.061%; margin-right: 10px;&quot; data-widthpercent=&quot;41.54&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDDOiU/btsGeRBoOAg/K0Vev3tVNcksr1QdzCNdV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDDOiU%2FbtsGeRBoOAg%2FK0Vev3tVNcksr1QdzCNdV0%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;848&quot; height=&quot;1230&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNFkJK/btsGc58Rp6g/d8LNGtrEHNamS1wbuZ5PYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNFkJK/btsGc58Rp6g/d8LNGtrEHNamS1wbuZ5PYK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;908&quot; data-origin-height=&quot;936&quot; data-filename=&quot;Untitled.png&quot; style=&quot;width: 57.7762%;&quot; data-widthpercent=&quot;58.46&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNFkJK/btsGc58Rp6g/d8LNGtrEHNamS1wbuZ5PYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNFkJK%2FbtsGc58Rp6g%2Fd8LNGtrEHNamS1wbuZ5PYK%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;908&quot; height=&quot;936&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p style=&quot;color: #333333; text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;글을 다&lt;span&gt;&amp;nbsp;&lt;/span&gt;쓰고 보니&lt;span&gt;&amp;nbsp;&lt;/span&gt;좋은 UX란?&lt;span&gt;&amp;nbsp;&lt;/span&gt;무엇인가에서부터&lt;span&gt;&amp;nbsp;&lt;/span&gt;시작해&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;인간관계, 좋은 제품까지 주제와 조금 동 떨어진 이야기도&lt;span&gt;&amp;nbsp;&lt;/span&gt;많이 했다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;FE 개발자로서 배울 것이 많고,&lt;span&gt;&amp;nbsp;&lt;/span&gt;해야 할&lt;span&gt;&amp;nbsp;&lt;/span&gt;것이 많지만&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;결론적으로 그런 것들이 좋은 UX를 제공하기 위한 기반이라고 생각해도 좋을 것 같다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;text-align: center;&quot; 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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>UX</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/218</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%A2%8B%EC%9D%80-UX%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8Cfeat-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90#entry218comment</comments>
      <pubDate>Sun, 31 Mar 2024 18:25:16 +0900</pubDate>
    </item>
    <item>
      <title>리눅스 자주 쓰는 명령어</title>
      <link>https://hmk1022.tistory.com/entry/%EB%A6%AC%EB%88%85%EC%8A%A4-%EC%9E%90%EC%A3%BC-%EC%93%B0%EB%8A%94-%EB%AA%85%EB%A0%B9%EC%96%B4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;주로&lt;span&gt; FE &lt;/span&gt;개발을&lt;span&gt; &lt;/span&gt;하고&lt;span&gt; &lt;/span&gt;있지만&lt;span&gt;, &lt;/span&gt;실무에서는&lt;span&gt; &lt;/span&gt;종종&lt;span&gt; &lt;/span&gt;리눅스&lt;span&gt; &lt;/span&gt;명령어를&lt;span&gt; &lt;/span&gt;사용해야&lt;span&gt;&amp;nbsp;하는 경우가 많습니다.&lt;/span&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;리눅스&lt;span&gt; &lt;/span&gt;명령어는&lt;span&gt; &lt;/span&gt;각종&lt;span&gt; &lt;/span&gt;테스트를&lt;span&gt; &lt;/span&gt;수행하거나&lt;span&gt; &lt;/span&gt;커널에&lt;span&gt; &lt;/span&gt;작업을&lt;span&gt; &lt;/span&gt;요청하거나&lt;span&gt; &lt;/span&gt;필요한&lt;span&gt; &lt;/span&gt;정보를&lt;span&gt; &lt;/span&gt;확인하는&lt;span&gt; &lt;/span&gt;데&lt;span&gt; &lt;/span&gt;유용합니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;또한&lt;span&gt;, CLI(Command Line Interface)&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;통해&lt;span&gt; &lt;/span&gt;작업하는&lt;span&gt; &lt;/span&gt;것이&lt;span&gt; GUI(Graphical User Interface)&lt;/span&gt;보다&lt;span&gt; &lt;/span&gt;업무&lt;span&gt; &lt;/span&gt;효율을&lt;span&gt; &lt;/span&gt;높일&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;마우스를&lt;span&gt; &lt;/span&gt;사용하는&lt;span&gt; &lt;/span&gt;것보다&lt;span&gt; &lt;/span&gt;키보드로&lt;span&gt; &lt;/span&gt;명령어를&lt;span&gt; &lt;/span&gt;입력하는&lt;span&gt; &lt;/span&gt;것이&lt;span&gt; &lt;/span&gt;시간을&lt;span&gt; &lt;/span&gt;절약할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;. (시간 -&amp;gt; 자원 -&amp;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;&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;시스템 관리&lt;/b&gt;: 리눅스는 다양한 서버 및 임베디드 시스템에서 널리 사용되며, 이러한 시스템을 관리하기 위해 명령줄 인터페이스를 사용하는 것이 효율적입니다. 기본 명령어를 알고 사용함으로써 파일 및 디렉토리 관리, 프로세스 관리, 네트워크 설정 등을 수행할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문제 해결&lt;/b&gt;: 시스템에서 문제가 발생했을 때, 명령줄 인터페이스를 사용하여 문제를 진단하고 해결하는 것이 효과적입니다. 로그 분석, 시스템 리소스 모니터링, 프로세스 관리 등을 위해 기본 명령어를 사용할 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;개발 환경&lt;/b&gt;: 개발자들은 주로 리눅스 환경에서 작업을 수행합니다. 리눅스 명령어를 알고 사용함으로써 개발 작업을 보다 효율적으로 수행할 수 있습니다. 예를 들어, 파일 관리, 버전 관리 시스템과의 상호 작용, 서버 설정 등에 사용될 수 있습니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;자동화&lt;/b&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;및&lt;/b&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;스크립팅&lt;/b&gt;&lt;span&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;리눅스&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;명령어를&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;사용하여&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;자동화된&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;작업이나&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;스크립트를&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;작성할&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;수&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;있습니다&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;이를&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;통해&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;반복적인&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;작업을&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;자동화하고&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;시스템&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;관리를&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;향상시킬&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;수&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;있습니다&lt;span&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&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. ls&lt;/h3&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;p data-ke-size=&quot;size16&quot;&gt;- 사용예시&lt;/p&gt;
&lt;pre id=&quot;code_1711857909274&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# ls                                   &amp;rarr; 현재 디렉터리의 파일 목록을 표시

# ls /etc/sysconfig /etc/sysconfig    &amp;rarr; 디렉터리의 목록을 표시

# ls -a                                &amp;rarr; 현재 디렉터리의 목록(숨김 파일 포함)을 표시

# ls -l                                 &amp;rarr; 현재 디렉터리의 목록을 자세히 표시

# ls *.cfg                             &amp;rarr; 확장자가 cfg인 목록을 표시

# ls -l /etc/sysconfig/a*             &amp;rarr; /etc/sysconfig 디렉터리 중 

                                          앞 글자가 'a'인 것의 목록을 자세히 표시&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. cd&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Change Directory의 약자로 디렉토리를 이동하는 명려입니다.&lt;/p&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_1711859197016&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# cd                       &amp;rarr; 현재 사용자의 홈 디렉터리로 이동,

                               만약 현재 사용자가 root면 '/root' 디렉터리로 이동

# cd ~rocky rocky        &amp;rarr; 사용자의 홈 디렉터리로 이동

# cd ..                    &amp;rarr; 바로 상위의 디렉터리로 이동

                              '..'은 현재 디렉터리의 부모 디렉터리를 의미,

                              예를 들어 현재 디렉터리가 /etc/sysconfig면 

                              바로 상위인 '/etc' 디렉터리로 이동

# cd /etc/sysconfig      &amp;rarr; /etc/sysconfig 디렉터리로 이동(절대 경로)

# cd ../etc/sysconfig    &amp;rarr; 상대 경로로 이동.

                             현재 디렉터리의 상위('..')로 이동한 후 

                             다시 /etc/sysconfig로 이동&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. pwd&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Print Working Directory의 약자로 현재 디렉터리의 전체 경로를 화면에 표시합니다.&lt;/p&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_1711859338090&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# pwd    &amp;rarr; 현재 작업 중인 디렉터리의 경로를 출력&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;size18&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;ex) .git, .gitignore&lt;/p&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4. rm&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ReMove의 약자로 파일이나 디렉터리를 삭제함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연히 파일이나 디렉터리를 삭제할 권한이 있어야 해당 명령어를 실행할 수 있음(ex. sudo, root 사용자)&lt;/p&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_1711859619746&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# rm abc.txt       &amp;rarr; 해당 파일을 삭제(내부적으로 'rm -i'로 연결됨)

# rm -i abc.txt    &amp;rarr; 삭제 시 정말 삭제할 지 확인하는 메시지를 표시

# rm -f abc.txt    &amp;rarr; 삭제 시 확인하지 않고 바로 삭제(f는 Force의 약자)

# rm -r abc        &amp;rarr; 해당 디렉터리를 삭제(r은 Recursive의 약자)

# rm -rf abc       &amp;rarr; r 옵션과 f 옵션을 합친 것으로 abc 디렉터리와 그 아래에 있는

                      하위 디렉터리를 강제로 전부 삭제(편리하지만 주의해서 사용해야 함)&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;5. cp&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CoPy의 약자로 파일이나 디렉터리를 복사.&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;pre id=&quot;code_1711859683151&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# cp abc.txt cba.txt     &amp;rarr; abc.txt를 cba.txt라는 이름으로 바꿔서 복사

# cp -r abc cda         &amp;rarr; 디렉터리 복사&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;6. touch&lt;/h3&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;size16&quot;&gt;- 사용예시&lt;/p&gt;
&lt;pre id=&quot;code_1711860576815&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# touch abc.txt    &amp;rarr; 파일이 없는 경우 abc.txt라는 빈 파일을 생성하고,

                       abc.tx 파일이 있는 경우 최종 수정 시간을 현재 시각으로 변경&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;7. mv&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MoVe의 약자로 디렉터리의 이름을 변경하거나 다른 디렉터리로 옮길 때&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_1711860674114&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# mv abc.txt /etc/sysconfig/     &amp;rarr; abc.txt을 /etc/sysconfig/ 디렉터리로 이동

# mv aaa bbb ccc ddd            &amp;rarr; aaa, bbb, ccc 파일을 /ddd 디렉터리로 이동

# mv abc.txt www.txt            &amp;rarr; abc.txt의 이름을 www.txt로 변경해서 이동&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;8. mkdir&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MaKe Directory의 약자로 새로운 디렉터리를 생성합니다.&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_1711860729810&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# mkdir abc            &amp;rarr; 현재 디렉터리 아래에 /abc 이름의 디렉터리 생성

# mkdir -p /def/fgh    &amp;rarr; /def/fgh 디렉터리를 생성. 만약 /fgh 디렉터리의 부모 디렉터리인

                           /def 디렉터리가 없다면 자동 생성(p는 Parents의 약자)&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;9. rmdir&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;RoMove Diretory의 약자로 디렉터리를 삭제합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 디렉터리의 삭제 권한이 있어야 하며 디렉터리는 비어야 있어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일이 있는 디렉터리를 삭제하려면 rm -r 명령을 실행해야합니다.&lt;/p&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_1711860808604&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# rmdir abc    &amp;rarr;    /abc 디렉터리를 삭제&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;10. cat&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;contCATenate의 약자로 파일 내용을 화면에 출력합니다. 여러 파일을 나열하면 파일을 연결해서 출력합니다.&lt;/p&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_1711860856252&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# cat a.txt    &amp;rarr; a.txt 파일의 내용을 화면에 출력&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;11. echo&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;pre id=&quot;code_1711861092746&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;echo [문자열]
# 문자열을 출력합니다

echo work.txt
# work.txt 파일의 문자열을 보여줍니다

echo new text &amp;gt; work.txt
# new text 문자열을 work.txt 파일에 있던 기존 내용을 삭제하고 추가합니다.


echo final text &amp;gt;&amp;gt; work.txt
# fianl text 문자열을 work.txt 파일의 끝 줄에 추가합니다.

echo $[환경변수명]
# 환경변수 내용을 출력합니다.&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;vim을 이용한 텍스트 파일 편집&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Vim&lt;/span&gt;은&lt;span&gt; &lt;/span&gt;많은&lt;span&gt; &lt;/span&gt;기능을&lt;span&gt; &lt;/span&gt;가진&lt;span&gt; &lt;/span&gt;텍스트&lt;span&gt; &lt;/span&gt;편집기로&lt;span&gt;, CLI&lt;/span&gt;에서&lt;span&gt; &lt;/span&gt;가장&lt;span&gt; &lt;/span&gt;많이&lt;span&gt; &lt;/span&gt;사용되는&lt;span&gt; &lt;/span&gt;편집기&lt;span&gt; &lt;/span&gt;중&lt;span&gt; &lt;/span&gt;하나입니다&lt;span&gt;. Vim &lt;/span&gt;만의&lt;span&gt; &lt;/span&gt;독특한&lt;span&gt; &lt;/span&gt;단축키가&lt;span&gt; &lt;/span&gt;처음에는&lt;span&gt; &lt;/span&gt;사용법을&lt;span&gt; &lt;/span&gt;익히기&lt;span&gt; &lt;/span&gt;어렵지만&lt;span&gt;, &lt;/span&gt;익숙해지면&lt;span&gt; &lt;/span&gt;높은&lt;span&gt; &lt;/span&gt;생산성을&lt;span&gt; &lt;/span&gt;얻을&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;&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;span&gt;2. vim [수정을 원하는 파일명]&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;492&quot; data-origin-height=&quot;234&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/REMpz/btsGgCi7pZn/KexvBzWpPx7jCSyTgbd511/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/REMpz/btsGgCi7pZn/KexvBzWpPx7jCSyTgbd511/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/REMpz/btsGgCi7pZn/KexvBzWpPx7jCSyTgbd511/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FREMpz%2FbtsGgCi7pZn%2FKexvBzWpPx7jCSyTgbd511%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;492&quot; height=&quot;234&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;234&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. i 키를 눌러 Insert 모드로 전환후 파일 내용수정&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;579&quot; data-origin-height=&quot;367&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LXnE7/btsGejyjr2l/UyzFEr89T7CDTrC8AWqAX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LXnE7/btsGejyjr2l/UyzFEr89T7CDTrC8AWqAX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LXnE7/btsGejyjr2l/UyzFEr89T7CDTrC8AWqAX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLXnE7%2FbtsGejyjr2l%2FUyzFEr89T7CDTrC8AWqAX1%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;579&quot; height=&quot;367&quot; data-origin-width=&quot;579&quot; data-origin-height=&quot;367&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;4. 파일내용 수정 후 &quot;ESC&quot; 키를 눌러 Normal 모드로 전환 후 &quot;:wq&quot;를 입력 후 엔ㄴ터키를 눌러 저장&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;576&quot; data-origin-height=&quot;365&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rpa5k/btsGc5gAp66/Ojs6ztSWxf5KOUr5oKQtEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rpa5k/btsGc5gAp66/Ojs6ztSWxf5KOUr5oKQtEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rpa5k/btsGc5gAp66/Ojs6ztSWxf5KOUr5oKQtEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frpa5k%2FbtsGc5gAp66%2FOjs6ztSWxf5KOUr5oKQtEk%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;576&quot; height=&quot;365&quot; data-origin-width=&quot;576&quot; data-origin-height=&quot;365&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>linux</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/217</guid>
      <comments>https://hmk1022.tistory.com/entry/%EB%A6%AC%EB%88%85%EC%8A%A4-%EC%9E%90%EC%A3%BC-%EC%93%B0%EB%8A%94-%EB%AA%85%EB%A0%B9%EC%96%B4#entry217comment</comments>
      <pubDate>Sun, 31 Mar 2024 14:06:35 +0900</pubDate>
    </item>
    <item>
      <title>팀을 위하는 개발자란?</title>
      <link>https://hmk1022.tistory.com/entry/%ED%8C%80%EC%9D%84-%EC%9C%84%ED%95%98%EB%8A%94-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%9E%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;코딩은 개발자들이 해야 하는 많은 일 중 하나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자의 필요조건일 뿐, 비즈니스 목적을 달성하기 위한 도구일 뿐&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&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;p data-ke-size=&quot;size16&quot;&gt;6. 사업 목표 이해하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;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;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;주위를 보면&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;존경받는 / 함께 일하고 싶은 / 팀에 큰 전력이 되는 개발자들은&lt;/p&gt;
&lt;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;크게 본질, 관계, 속마음 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;&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;905&quot; data-origin-height=&quot;417&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vnYiS/btsGfwJ7HM5/daboEvAmw9VJlpFeNm79nk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vnYiS/btsGfwJ7HM5/daboEvAmw9VJlpFeNm79nk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vnYiS/btsGfwJ7HM5/daboEvAmw9VJlpFeNm79nk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvnYiS%2FbtsGfwJ7HM5%2FdaboEvAmw9VJlpFeNm79nk%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;786&quot; height=&quot;362&quot; data-origin-width=&quot;905&quot; data-origin-height=&quot;417&quot;/&gt;&lt;/span&gt;&lt;/figure&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;1. 본질&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Situation 1&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느 날 PM이 말했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;신분증 인증에서 사용자가 많이 나가네요.&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;좋아요 :) 프런트 공수는 얼마 안 들어요~&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Don't&lt;/b&gt;&lt;/span&gt;&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;&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;팀플레이어다운 응답&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;&quot;우리 인증서 활용동의&quot;를 받으면&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;Do&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;근본 문제 파악 -&amp;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;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;Learning&lt;/b&gt;&lt;/span&gt;&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;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;&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Situation 2&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&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;&quot;실수했네요, 앞으로 더 신경 쓰겠습니다.&quot;&lt;/p&gt;
&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;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Don't&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제상황 1차원적 검토&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&amp;gt; 문제 재발 시 개발자 역량 부족으로 비침&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&amp;gt; &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;QA의 부족 등등 더 복합적 문제가 있음에도 원인 탐구기회 자체가 없어짐&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;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;팀플레이어다운 응답&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;출시 후 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;일례로 지난주의 버그는 자칫했다간 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;b&gt;팀 차원에서 리스크의 심각성을 인지하고, 해결책을 논의해 봐요.&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;팀플레이어 동료들의 응답&lt;/b&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;일정 관점 - &quot;공감합니다. 기능 개발과 코드 개선이 변행 되도록 일정을 잡아봐요.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소 테스트 관점 - &quot;금액 정합성 테스트만 넣어도 리스크를 줄일 수 있겠어요.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;QA환경 개선 접근 - &quot;음, 저는 손테스트조차 하기 어려운 환경이 원인인 것 같아요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자 도움 없이도 기능테스트가 가능하도록 어드민을 만들면 어때요?&quot;&lt;/p&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: #8a3db6;&quot;&gt;&lt;b&gt;Learning&lt;/b&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;- 목표 달성을 위한 최선의 방법을 찾아내자&lt;/p&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;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;1. 관계&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Situation 1&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어느 날 PM이 말했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;외부사 API 완료일이 또 늦어졌네요...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일주일 더 필요하대요. 저희 릴리즈 일정 괜찮을까요?&quot;&lt;/p&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;응답&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;저희 일정도 늦어지죠... 저희도 일주일 추가하면 될 것 같아요.&quot;&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: #ee2323;&quot;&gt;&lt;b&gt;Don't&lt;/b&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;일정의 불확실성 증가('또 미뤄지면 어떡하지?')&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;팀플레이어다운 응답&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;외부사 API가 &lt;b&gt;늦어도 X일&lt;/b&gt;까지 되지 않으면&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;버퍼로 잡아둔 목표일정인 Y일이 불가해요.&lt;/p&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;스펙 줄여서 Y일까지 되게 만들던지, 아니면 일정을 조정해 봐요.&quot;&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;Do&lt;/b&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;듣는 이가 궁금한 &quot;목표일까지 되어야 하는데...&quot;에 대한 해결책도 함께 전달&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Situation 2&lt;/h4&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 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;size18&quot;&gt;&lt;b&gt;응답&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;오... 꽤 기능이 많은 페이지네요. 2주 내로 배포 목표해 볼게요.&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(그리고 일정에 쫓겨 야근한다.)&lt;br /&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;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Don't&lt;/b&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;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;팀플레이어다운 응답&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;/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;&quot;2주가량 걸릴 큰 스펙이네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 X, Y는 동일 목적의 기능으로 보이는데요, 어떤가요?&quot;&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(디자이너 응답 듣고)&quot;둘을 간소화해서 개발 및 운영 공수를 줄이면&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;오픈 후 데이터 보고 발전시키면 어떨까요?&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;Learning&lt;/b&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;중요도를 파악해 적극적으로 스펙을 줄인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발공수를 투명한 전파 -&amp;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;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;1. 말하지 않는 것을 알아낸다.&lt;/h3&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Situation 1&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;&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;질문&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;요즘 잘 지내세요?&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Don't&lt;/b&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;요약해서 답변하게 되어 구체적인 이야기로 들어가기 어려움&lt;/p&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: #409d00;&quot;&gt;&lt;b&gt;팀플레이어다운 장치&lt;/b&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;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;&amp;nbsp;&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: #409d00;&quot;&gt;&lt;b&gt;Do&lt;/b&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;나만 하는 고민이 아님을 알기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정기적 욕구파악 -&amp;gt; 성장할 수 있는 방향의 일을 하도록 돕기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Situation 2&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거시적 관점이 있는 PM에게 물어보자.&lt;/p&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;질문&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;요즘 XX 한 문제가 있는 것 같아요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해결하기 위해 제가 더 할 수 있는 일이 있을까요?&quot;&lt;/p&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: #ee2323;&quot;&gt;&lt;b&gt;Don't&lt;/b&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;답변이 XX 문제에 집중됨(이상의 문제가 있을 수 있는데)&lt;/p&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;size18&quot;&gt;&lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;팀플레이어다운 질문&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;요즘 일할 때 XX가 잘 안 된다고 느껴져요... PM님은 어떠세요?&quot;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PM이 관련한 고민과 시도를 전달해 줌 -&amp;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;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;Do&lt;/b&gt;&lt;/span&gt;&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;-&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;Learning&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포괄적 질문은 -&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;상황을 &lt;b&gt;쉽게! 떠올릴 수 있도록 질문&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;e.g&amp;nbsp; 커뮤니케이션에 대한 철학을 말해주세요 (X)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 프로젝트에서 동료가 어려움을 겪었을 때 어떤 행동을 하셨나요? (O)&lt;/p&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; 진실을 찾아낼 수 있는 접근&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&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;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;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;- 이들이 말하지 않은&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;size18&quot;&gt;-&amp;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;&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;앞으로 1달간, &lt;b&gt;동료의 멋진 행동 3개 모아 보기&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;gt; 나중에 10개 모이면 정리&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;b&gt;사례 예시)&lt;/b&gt;&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;&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;Action Item&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;나의 Action Item&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;- 1년 뒤에 &lt;b&gt;이불킥 하기&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;do, don't를 현재 제 뇌에서 짜낼 수 있는 가장 좋은 방법으로 적었지만,&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;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;b&gt;Reference&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;&lt;a href=&quot;https://www.youtube.com/watch?v=ZYKcD2gKlvg&amp;amp;t=1013s&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=ZYKcD2gKlvg&amp;amp;t=1013s&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <category>company</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/216</guid>
      <comments>https://hmk1022.tistory.com/entry/%ED%8C%80%EC%9D%84-%EC%9C%84%ED%95%98%EB%8A%94-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%9E%80#entry216comment</comments>
      <pubDate>Sat, 30 Mar 2024 17:02:50 +0900</pubDate>
    </item>
    <item>
      <title>알아두면 쓸데 있는 GOF 디자인 패턴</title>
      <link>https://hmk1022.tistory.com/entry/%EC%95%8C%EC%95%84%EB%91%90%EB%A9%B4-%EC%93%B8%EB%8D%B0-%EC%9E%88%EB%8A%94-GOF-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;디자인&lt;span&gt; &lt;/span&gt;패턴은&lt;span&gt; &lt;/span&gt;프로그램을&lt;span&gt; &lt;/span&gt;개발하는&lt;span&gt; &lt;/span&gt;과정에서&lt;span&gt; &lt;/span&gt;빈번하게&lt;span&gt; &lt;/span&gt;발생하는&lt;span&gt; &lt;br /&gt;&lt;/span&gt;디자인&lt;span&gt;&amp;nbsp;설계&lt;/span&gt;문제를&lt;span&gt; &lt;/span&gt;정리해서&lt;span&gt; &lt;/span&gt;상황에&lt;span&gt; &lt;/span&gt;따라&lt;span&gt; &lt;/span&gt;간편하게&lt;span&gt; &lt;/span&gt;적용할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있게&lt;span&gt; &lt;/span&gt;정리한&lt;span&gt; &lt;/span&gt;것입니다&lt;span&gt;.&amp;nbsp;&lt;br /&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 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;b&gt;잘&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;활용할&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;수만&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;있다면&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;적지&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;않은&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;시간과&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;노력&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;시행착오를&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;줄일&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;수&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;h3 style=&quot;color: #222222; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;디자인 패턴 용도에 따라 나누기&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;&lt;/span&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;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;가장 대중적으로 널리 알려진 나누는 기준은 &lt;b&gt;생성, 구조, 행동&lt;/b&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;777&quot; data-origin-height=&quot;574&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJxBvJ/btsF7ZFVdyi/CQ0B8ggBj6NVJ8OMgvbfX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJxBvJ/btsF7ZFVdyi/CQ0B8ggBj6NVJ8OMgvbfX1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJxBvJ/btsF7ZFVdyi/CQ0B8ggBj6NVJ8OMgvbfX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJxBvJ%2FbtsF7ZFVdyi%2FCQ0B8ggBj6NVJ8OMgvbfX1%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;777&quot; height=&quot;574&quot; data-origin-width=&quot;777&quot; data-origin-height=&quot;574&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;생성 패턴(Creational Pattern)&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 인스턴스를 생성하는 패턴으로, 객체를&lt;span&gt; &lt;/span&gt;생성하는&lt;span&gt; &lt;/span&gt;방법과&lt;span&gt; &lt;/span&gt;시점을&lt;span&gt; &lt;/span&gt;추상화하고&lt;span&gt;, &lt;/span&gt;코드의&lt;span&gt; &lt;/span&gt;유연성&lt;span&gt;, &lt;/span&gt;재사용성&lt;span&gt; &lt;/span&gt;및&lt;span&gt; &lt;/span&gt;유지보수성을&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;싱글턴 패턴(Singleton Pattern)&lt;/span&gt;&lt;/h4&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;span&gt; &lt;/span&gt;인스턴스가&lt;span&gt; &lt;/span&gt;오직&lt;span&gt; &lt;/span&gt;하나만&lt;span&gt; &lt;/span&gt;생성되도록&lt;span&gt; &lt;/span&gt;보장하는&lt;span&gt; &lt;/span&gt;패턴&lt;/b&gt;입니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;이&lt;span&gt; &lt;/span&gt;패턴을&lt;span&gt; &lt;/span&gt;사용하면&lt;span&gt; &lt;/span&gt;해당&lt;span&gt; &lt;/span&gt;클래스의&lt;span&gt; &lt;/span&gt;인스턴스에&lt;span&gt; &lt;/span&gt;전역적으로&lt;span&gt; &lt;/span&gt;접근할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있는&lt;span&gt; &lt;/span&gt;지점을&lt;span&gt; &lt;/span&gt;제공하여&lt;span&gt;, &lt;/span&gt;어디서든&lt;span&gt; &lt;/span&gt;해당&lt;span&gt; &lt;/span&gt;인스턴스에&lt;span&gt; &lt;/span&gt;접근할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있게&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;싱글톤&lt;span&gt; &lt;/span&gt;패턴은&lt;span&gt; &lt;/span&gt;주로&lt;span&gt; &lt;/span&gt;리소스&lt;span&gt; &lt;/span&gt;&lt;b&gt;공유&lt;span&gt;, &lt;/span&gt;로깅&lt;span&gt;, &lt;/span&gt;캐시&lt;span&gt;, &lt;/span&gt;설정&lt;span&gt; &lt;/span&gt;관리&lt;/b&gt;&lt;span&gt; &lt;/span&gt;등과&lt;span&gt; &lt;/span&gt;같이&lt;span&gt; &lt;/span&gt;시스템&lt;span&gt; &lt;/span&gt;전반에&lt;span&gt; &lt;/span&gt;걸쳐&lt;span&gt; &lt;/span&gt;단&lt;span&gt; &lt;/span&gt;하나의&lt;span&gt; &lt;/span&gt;인스턴스만&lt;span&gt; &lt;/span&gt;필요한&lt;span&gt; &lt;/span&gt;경우에&lt;span&gt; &lt;/span&gt;사용됩니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;그러나&lt;span&gt; &lt;/span&gt;싱글톤&lt;span&gt; &lt;/span&gt;패턴은&lt;span&gt; &lt;/span&gt;전역&lt;span&gt; &lt;/span&gt;상태를&lt;span&gt; &lt;/span&gt;만들어내는&lt;span&gt; &lt;/span&gt;것이므로&lt;span&gt; &lt;/span&gt;남발하면&lt;span&gt; &lt;/span&gt;코드의&lt;span&gt; &lt;/span&gt;유지보수성과&lt;span&gt; &lt;/span&gt;테스트&lt;span&gt; &lt;/span&gt;용이성에&lt;span&gt; &lt;/span&gt;부정적인&lt;span&gt; &lt;/span&gt;영향을&lt;span&gt; &lt;/span&gt;줄&lt;span&gt; &lt;/span&gt;수&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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&gt; &lt;/span&gt;종종&lt;span&gt; &lt;/span&gt;&lt;b&gt;하나의&lt;span&gt; &lt;/span&gt;객체를&lt;span&gt; &lt;/span&gt;프로그램&lt;span&gt; &lt;/span&gt;내에서&lt;span&gt; &lt;/span&gt;공유&lt;/b&gt;하고&lt;span&gt; &lt;/span&gt;싶을&lt;span&gt; &lt;/span&gt;때가&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;br /&gt;&lt;/span&gt;예를&lt;span&gt; &lt;/span&gt;들어&lt;span&gt;, &lt;/span&gt;데이터베이스&lt;span&gt; &lt;/span&gt;연결&lt;span&gt;, &lt;/span&gt;로그&lt;span&gt; &lt;/span&gt;라이터&lt;span&gt; &lt;/span&gt;등과&lt;span&gt; &lt;/span&gt;같은&lt;span&gt; &lt;/span&gt;리소스를&lt;span&gt; &lt;/span&gt;효율적으로&lt;span&gt; &lt;/span&gt;활용하고자&lt;span&gt; &lt;/span&gt;할&lt;span&gt; &lt;/span&gt;때가&lt;span&gt; &lt;/span&gt;그러한&lt;span&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;/span&gt;새로운&lt;span&gt; &lt;/span&gt;객체를&lt;span&gt; &lt;/span&gt;생성하는&lt;span&gt; &lt;/span&gt;것은&lt;span&gt; &lt;/span&gt;비효율적일&lt;span&gt; &lt;/span&gt;뿐만&lt;span&gt; &lt;/span&gt;아니라&lt;span&gt; &lt;/span&gt;예기치&lt;span&gt; &lt;/span&gt;못한&lt;span&gt; &lt;/span&gt;문제를&lt;span&gt; &lt;/span&gt;초래할&lt;span&gt; &lt;/span&gt;수&lt;span&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 data-ke-size=&quot;size16&quot;&gt;싱글턴&lt;span&gt; &lt;/span&gt;패턴은&lt;span&gt; &lt;/span&gt;클래스의&lt;span&gt; &lt;/span&gt;인스턴스가&lt;span&gt; &lt;/span&gt;하나만&lt;span&gt; &lt;/span&gt;생성되도록&lt;span&gt; &lt;/span&gt;보장하고&lt;span&gt;, &lt;/span&gt;그&lt;span&gt; &lt;/span&gt;인스턴스에&lt;span&gt; &lt;/span&gt;대한&lt;span&gt; &lt;/span&gt;전역적인&lt;span&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;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bozObN/btsF5U6GjKz/TySgzoq0u8P83gYX9Axt7k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bozObN/btsF5U6GjKz/TySgzoq0u8P83gYX9Axt7k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bozObN/btsF5U6GjKz/TySgzoq0u8P83gYX9Axt7k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbozObN%2FbtsF5U6GjKz%2FTySgzoq0u8P83gYX9Axt7k%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;800&quot; height=&quot;328&quot; data-origin-width=&quot;800&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;추상 팩토리 패턴(Abstract Factory Pattern)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서로&lt;span&gt; &lt;/span&gt;관련된&lt;span&gt; &lt;/span&gt;객체들의&lt;span&gt; &lt;/span&gt;집합을&lt;span&gt; &lt;/span&gt;생성하기&lt;span&gt; &lt;/span&gt;위한&lt;span&gt; &lt;/span&gt;인터페이스를&lt;span&gt; &lt;/span&gt;제공합니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;이&lt;span&gt; &lt;/span&gt;패턴은&lt;span&gt; &lt;/span&gt;&lt;b&gt;클라이언트&lt;span&gt; &lt;/span&gt;코드가&lt;span&gt; &lt;/span&gt;구상&lt;span&gt; &lt;/span&gt;클래스를&lt;span&gt; &lt;/span&gt;직접&lt;span&gt; &lt;/span&gt;생성하는&lt;span&gt; &lt;/span&gt;것이&lt;span&gt; &lt;/span&gt;아니라&lt;span&gt;, &lt;/span&gt;팩토리&lt;span&gt; &lt;/span&gt;객체를&lt;span&gt; &lt;/span&gt;통해&lt;span&gt; &lt;/span&gt;객체를&lt;span&gt; &lt;/span&gt;생성하고&lt;span&gt; &lt;/span&gt;관리하도록&lt;span&gt; &lt;/span&gt;합니다&lt;span&gt;.&lt;/span&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용예시&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;간단한&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;모바일&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;전략&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;게임을&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;개발&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;중입니다&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;이&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;게임에서는&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;유닛&lt;span&gt;(&lt;/span&gt;병사&lt;span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;기병&lt;span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;궁수&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;등&lt;span&gt;)&lt;/span&gt;을&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;생성해야&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;합니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;각&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;유닛은&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;공격력&lt;span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;방어력&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;등의&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;속성을&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;가지고&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;있으며&lt;span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;다른&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;유닛들과&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;전투 혹은 방어&lt;/b&gt;를 할&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;수&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;있어야&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;합니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러한&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;상황에서&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;추상&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;팩토리&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;패턴을&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;활용할&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;수&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;있습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;코드&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1711632657041&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;// 추상 유닛 클래스
abstract class Unit {
    abstract attack(): void;
    abstract defend(): void;
}

// 병사 클래스
class Infantry extends Unit {
    attack(): void {
        console.log(&quot;Infantry attacks with sword.&quot;);
    }

    defend(): void {
        console.log(&quot;Infantry defends with shield.&quot;);
    }
}

// 궁수 클래스
class Archer extends Unit {
    attack(): void {
        console.log(&quot;Archer attacks with bow and arrow.&quot;);
    }

    defend(): void {
        console.log(&quot;Archer defends with evasion.&quot;);
    }
}

// 추상 팩토리 인터페이스
interface ArmyFactory {
    createUnit(): Unit;
}

// 병사를 생성하는 구체적인 팩토리 클래스
class InfantryFactory implements ArmyFactory {
    createUnit(): Unit {
        return new Infantry();
    }
}

// 궁수를 생성하는 구체적인 팩토리 클래스
class ArcherFactory implements ArmyFactory {
    createUnit(): Unit {
        return new Archer();
    }
}

// 게임 클라이언트
class GameClient {
    constructor(private factory: ArmyFactory) {}

    prepareArmy(): void {
        const unit = this.factory.createUnit();
        unit.attack();
        unit.defend();
    }
}

// 테스트
const infantryFactory = new InfantryFactory();
const archerFactory = new ArcherFactory();

const gameClient = new GameClient(infantryFactory);
gameClient.prepareArmy();

const gameClient2 = new GameClient(archerFactory);
gameClient2.prepareArmy();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WeWzJ/btsF5tuZetJ/A6kckBE10gPYLk9PflpKs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WeWzJ/btsF5tuZetJ/A6kckBE10gPYLk9PflpKs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WeWzJ/btsF5tuZetJ/A6kckBE10gPYLk9PflpKs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWeWzJ%2FbtsF5tuZetJ%2FA6kckBE10gPYLk9PflpKs1%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;800&quot; height=&quot;636&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;팩토리 메서드 패턴(Abstract Factory Pattern)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이&lt;span&gt; &lt;/span&gt;패턴은&lt;span&gt; &lt;/span&gt;객체를&lt;span&gt; &lt;/span&gt;생성하기&lt;span&gt; &lt;/span&gt;위한&lt;span&gt; &lt;/span&gt;인터페이스를&lt;span&gt; &lt;/span&gt;정의하고&lt;span&gt;, &lt;/span&gt;&lt;b&gt;객체의&lt;span&gt; &lt;/span&gt;생성을&lt;span&gt; &lt;/span&gt;서브&lt;span&gt; &lt;/span&gt;클래스에&lt;span&gt; &lt;/span&gt;위임하여&lt;span&gt; &lt;/span&gt;객체&lt;span&gt; &lt;/span&gt;생성&lt;span&gt; &lt;/span&gt;방법을&lt;span&gt; &lt;/span&gt;캡슐화&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;메시지의 타입에 따라 각기 다른 클래스 인스턴스를 반환하는 PacketFactory&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1711632788614&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export class PacketFactory {
  static createProcessor&amp;lt;T, G&amp;gt;(type: MessageType): PacketProcessor&amp;lt;T, G&amp;gt; {
    let processor;

    switch (type) {
      case 'authentication':
        processor = new AuthenticationProcessor();
        break;
      case 'exchangeRate':
        processor = new ExchangeRateProcessor();
        break;
      case 'keywordAnalysis':
        processor = new NaverKeywordTrendProcessor();
        break;
      case 'getHTMLStringFromUrl':
        processor = new ScrapHtmlProcessor();
        break;
      case 'getNaverImageSearch':
        processor = new NaverImageSearchProcessor();
        break;
      case 'getAccessToken':
        processor = new AccessTokenProcessor();
        break;
      case 'sendProduct':
        processor = new ProductProcessor();
        break;
      case 'taobaoImageSearch':
        processor = new TaobaoImageSearchProcessor();
        break;
      case 'taobaoProductSearch':
        processor = new TaobaoProductSearchProcessor();
        break;
      case 'getMainKeyword':
        processor = new MainKeywordProcessor();
        break;
      case 'getBlobs':
        processor = new BlobConvertProcessor();
        break;
      default:
        throw new Error(`no process for ${type}`);
    }

    return processor;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;397&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oy6Aq/btsF56zd06S/sdNuHp18s6ELpkSP0AG67K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oy6Aq/btsF56zd06S/sdNuHp18s6ELpkSP0AG67K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oy6Aq/btsF56zd06S/sdNuHp18s6ELpkSP0AG67K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Foy6Aq%2FbtsF56zd06S%2FsdNuHp18s6ELpkSP0AG67K%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;800&quot; height=&quot;397&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;397&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;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;span&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;팩토리&lt;/b&gt;&lt;span&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;패턴&lt;/b&gt;&lt;span&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;관련된&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;객체들의&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;집합을&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;생성하기&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;위한&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;인터페이스를&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;제공&lt;/b&gt;하고&lt;span&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;해당&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;인터페이스의&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;구현을&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;통해&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;객체&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;생성을&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;위임&lt;/b&gt;합니다&lt;span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;여러&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;종류의&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;관련&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;객체를&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;생성할&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;때&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;사용됩니다&lt;span&gt;.&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;b&gt;팩토리 메서드 패턴&lt;/b&gt;: &lt;b&gt;객체를 생성하는 인터페이스를 정의&lt;/b&gt;하고, 이를 서&lt;b&gt;브 클래스에서 구현하여 객체 생성 방법을 변경할 수 있도록 합니다.&lt;/b&gt; 즉, 객체 생성을 처리하는 로직을 Creator 클래스와 Concrete Creator 클래스로 분리합니다.&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;행동 패턴(Behavioral Pattern)&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체&lt;span&gt; &lt;/span&gt;간의&lt;span&gt; &lt;/span&gt;상호작용과&lt;span&gt; &lt;/span&gt;책임&lt;span&gt; &lt;/span&gt;분배에&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;템플릿 메소드 패턴(Abstract Factory Pattern)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;알고리즘의&lt;span&gt; &lt;/span&gt;뼈대를&lt;span&gt; &lt;/span&gt;정의&lt;/b&gt;하고&lt;span&gt; &lt;/span&gt;알고리즘의&lt;span&gt; &lt;/span&gt;일부를&lt;span&gt; &lt;/span&gt;서브클래스로&lt;span&gt; &lt;/span&gt;디자인&lt;span&gt; &lt;/span&gt;패턴&lt;span&gt; &lt;/span&gt;확장하여&lt;span&gt; &lt;br /&gt;&lt;/span&gt;&lt;b&gt;알고리즘의&lt;span&gt; &lt;/span&gt;일부를&lt;span&gt; &lt;/span&gt;재정의할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있도록&lt;span&gt; &lt;/span&gt;하는&lt;span&gt; &lt;/span&gt;패턴&lt;/b&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;템플릿&lt;span&gt; &lt;/span&gt;메소드&lt;span&gt; &lt;/span&gt;패턴은&lt;span&gt; &lt;/span&gt;코드의&lt;span&gt; &lt;/span&gt;중복을&lt;span&gt; &lt;/span&gt;줄이고&lt;span&gt; &lt;/span&gt;유연성을&lt;span&gt; 향상시킵니다향상합니다. &lt;br /&gt;&lt;/span&gt;&lt;b&gt;공통으로&lt;span&gt; &lt;/span&gt;사용되는&lt;span&gt; &lt;/span&gt;알고리즘의&lt;span&gt; &lt;/span&gt;구조를&lt;span&gt; &lt;/span&gt;한&lt;span&gt; &lt;/span&gt;곳에&lt;span&gt; &lt;/span&gt;유지&lt;/b&gt;하면서&lt;span&gt;, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;알고리즘의&lt;span&gt; &lt;/span&gt;일부를&lt;span&gt; &lt;/span&gt;서브클래스에서&lt;span&gt; &lt;/span&gt;오버라이드&lt;/b&gt;하여&lt;span&gt; &lt;/span&gt;다양한&lt;span&gt; &lt;/span&gt;구현을&lt;span&gt; &lt;/span&gt;제공할&lt;span&gt; &lt;/span&gt;수&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&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&gt; &lt;/span&gt;생산하는&lt;span&gt; &lt;/span&gt;공장을&lt;span&gt; &lt;/span&gt;운영한다고&lt;span&gt; 가정해봅시다가정해 봅시다. &lt;br /&gt;&lt;/span&gt;공장에서는&lt;span&gt; &lt;/span&gt;제품을&lt;span&gt; &lt;/span&gt;생산하기&lt;span&gt; &lt;/span&gt;위한&lt;span&gt; &lt;/span&gt;&lt;b&gt;표준적인&lt;span&gt; &lt;/span&gt;절차&lt;/b&gt;가&lt;span&gt; &lt;/span&gt;있을&lt;span&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;/span&gt;패턴을&lt;span&gt; &lt;/span&gt;사용하여&lt;span&gt; &lt;/span&gt;구현할&lt;span&gt; &lt;/span&gt;수&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;코드&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1711633069193&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 전자제품 클래스
abstract class ElectronicsProduct {
    // 제품 생산의 템플릿 메소드
    produce(): void {
        this.assembleComponents();
        this.testProduct();
        this.packageProduct();
    }

    // 제품을 조립하는 단계
    abstract assembleComponents(): void;

    // 제품을 테스트하는 단계
    abstract testProduct(): void;

    // 제품을 포장하는 단계
    abstract packageProduct(): void;
}

// 스마트폰 클래스
class Smartphone extends ElectronicsProduct {
    assembleComponents(): void {
        console.log(&quot;Assembling smartphone components.&quot;);
    }

    testProduct(): void {
        console.log(&quot;Testing smartphone functionality.&quot;);
    }

    packageProduct(): void {
        console.log(&quot;Packaging smartphone for shipment.&quot;);
    }
}

// 노트북 클래스
class Laptop extends ElectronicsProduct {
    assembleComponents(): void {
        console.log(&quot;Assembling laptop components.&quot;);
    }

    testProduct(): void {
        console.log(&quot;Testing laptop functionality.&quot;);
    }

    packageProduct(): void {
        console.log(&quot;Packaging laptop for shipment.&quot;);
    }
}

// 테스트
const smartphone = new Smartphone();
smartphone.produce();
console.log(&quot;---------------------&quot;);
const laptop = new Laptop();
laptop.produce();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOgEL4/btsF8a1IPCI/xTmnMkGZxfkJAECeeWeBwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOgEL4/btsF8a1IPCI/xTmnMkGZxfkJAECeeWeBwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOgEL4/btsF8a1IPCI/xTmnMkGZxfkJAECeeWeBwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOgEL4%2FbtsF8a1IPCI%2FxTmnMkGZxfkJAECeeWeBwk%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;800&quot; height=&quot;498&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;498&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;상태 패턴(State Pattern)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;객체의&lt;span&gt; &lt;/span&gt;내부&lt;span&gt; &lt;/span&gt;상태가&lt;span&gt; &lt;/span&gt;바뀔&lt;span&gt; &lt;/span&gt;때&lt;span&gt; &lt;/span&gt;객체의&lt;span&gt; &lt;/span&gt;행동을&lt;span&gt; &lt;/span&gt;변경할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있도록&lt;span&gt; &lt;/span&gt;하는&lt;span&gt; &lt;/span&gt;패턴&lt;/b&gt;입니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;객체의&lt;span&gt; &lt;/span&gt;행동은&lt;span&gt; &lt;/span&gt;현재&lt;span&gt; &lt;/span&gt;상태에&lt;span&gt; &lt;/span&gt;따라&lt;span&gt; &lt;/span&gt;달라지며&lt;span&gt;, &lt;/span&gt;상태를&lt;span&gt; &lt;/span&gt;객체로&lt;span&gt; &lt;/span&gt;캡슐화하여&lt;span&gt; &lt;/span&gt;상태에&lt;span&gt; &lt;/span&gt;따른&lt;span&gt; &lt;/span&gt;행동을&lt;span&gt; &lt;/span&gt;별도로&lt;span&gt; &lt;/span&gt;구현합니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;이&lt;span&gt; &lt;/span&gt;패턴은&lt;span&gt; &lt;/span&gt;객체가&lt;span&gt; &lt;/span&gt;다양한&lt;span&gt; &lt;/span&gt;상태를&lt;span&gt; &lt;/span&gt;가질&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있고&lt;span&gt;, &lt;/span&gt;각&lt;span&gt; &lt;/span&gt;상태에&lt;span&gt; &lt;/span&gt;따라&lt;span&gt; &lt;/span&gt;다르게&lt;span&gt; &lt;/span&gt;동작해야&lt;span&gt; &lt;/span&gt;할&lt;span&gt; &lt;/span&gt;때&lt;span&gt; &lt;/span&gt;유용하게&lt;span&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 data-ke-size=&quot;size18&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;자판기를&lt;span&gt; &lt;/span&gt;상태&lt;span&gt; &lt;/span&gt;패턴으로&lt;span&gt; &lt;/span&gt;구현한다고&lt;span&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;b&gt;자판기는&lt;span&gt; &lt;/span&gt;여러&lt;span&gt; &lt;/span&gt;가지&lt;span&gt; &lt;/span&gt;상태를&lt;span&gt; &lt;/span&gt;가질&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;. &lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를&lt;span&gt; &lt;/span&gt;들어&lt;span&gt;, &quot;&lt;/span&gt;동전&lt;span&gt; &lt;/span&gt;투입&lt;span&gt; &lt;/span&gt;대기&lt;span&gt;&quot;, &quot;&lt;/span&gt;음료수&lt;span&gt; &lt;/span&gt;선택&lt;span&gt; &lt;/span&gt;대기&lt;span&gt;&quot;, &quot;&lt;/span&gt;음료수&lt;span&gt; &lt;/span&gt;배출&lt;span&gt; &lt;/span&gt;대기&lt;span&gt;&quot; &lt;/span&gt;등의&lt;span&gt; &lt;/span&gt;상태가&lt;span&gt; &lt;/span&gt;있을&lt;span&gt; &lt;/span&gt;수&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;코드&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1711633159162&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 상태 인터페이스
interface VendingMachineState {
    insertCoin(): void;
    selectItem(): void;
    dispenseItem(): void;
}

// 자판기 클래스
class VendingMachine {
    private state: VendingMachineState;

    constructor(state: VendingMachineState) {
        this.state = state;
    }

    // 상태 변경 메소드
    setState(state: VendingMachineState) {
        this.state = state;
    }

    // 자판기의 행동 메소드
    insertCoin() {
        this.state.insertCoin();
    }

    selectItem() {
        this.state.selectItem();
    }

    dispenseItem() {
        this.state.dispenseItem();
    }
}

// 각 상태에 따른 클래스 구현
class WaitForCoin implements VendingMachineState {
    insertCoin() {
        console.log(&quot;동전을 투입했습니다.&quot;);
        // 다음 상태로 변경
        vendingMachine.setState(new SelectItem());
    }

    selectItem() {
        console.log(&quot;동전을 먼저 투입해주세요.&quot;);
    }

    dispenseItem() {
        console.log(&quot;음료수를 선택해주세요.&quot;);
    }
}

class SelectItem implements VendingMachineState {
    insertCoin() {
        console.log(&quot;이미 동전이 투입되었습니다.&quot;);
    }

    selectItem() {
        console.log(&quot;음료수를 선택했습니다.&quot;);
        // 다음 상태로 변경
        vendingMachine.setState(new DispenseItem());
    }

    dispenseItem() {
        console.log(&quot;음료수를 먼저 선택해주세요.&quot;);
    }
}

class DispenseItem implements VendingMachineState {
    insertCoin() {
        console.log(&quot;이미 동전이 투입되었습니다.&quot;);
    }

    selectItem() {
        console.log(&quot;이미 음료수가 선택되었습니다.&quot;);
    }

    dispenseItem() {
        console.log(&quot;음료수를 배출합니다.&quot;);
    }
}

// 테스트
const vendingMachine = new VendingMachine(new WaitForCoin());
vendingMachine.insertCoin(); // 동전을 투입했습니다.
vendingMachine.selectItem(); // 음료수를 선택해주세요.
vendingMachine.dispenseItem(); // 음료수를 선택해주세요.&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;419&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qTg57/btsF41ea6nR/ZXwvk7iz2Ryu6F2C0fqZUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qTg57/btsF41ea6nR/ZXwvk7iz2Ryu6F2C0fqZUk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qTg57/btsF41ea6nR/ZXwvk7iz2Ryu6F2C0fqZUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqTg57%2FbtsF41ea6nR%2FZXwvk7iz2Ryu6F2C0fqZUk%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;800&quot; height=&quot;419&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;419&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;반복자 패턴( iterator Pattern)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;객체들의&lt;span&gt; &lt;/span&gt;집합을&lt;span&gt; &lt;/span&gt;순차적으로&lt;span&gt; &lt;/span&gt;접근하고&lt;span&gt; &lt;/span&gt;조작하기&lt;span&gt; &lt;/span&gt;위한&lt;span&gt; &lt;/span&gt;디자인&lt;span&gt; &lt;/span&gt;패턴&lt;/b&gt;입니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;이&lt;span&gt; &lt;/span&gt;패턴은&lt;span&gt; &lt;/span&gt;컬렉션의&lt;span&gt; &lt;/span&gt;내부&lt;span&gt; &lt;/span&gt;구조에&lt;span&gt; &lt;/span&gt;독립적으로&lt;span&gt; &lt;/span&gt;컬렉션의&lt;span&gt; &lt;/span&gt;요소를&lt;span&gt; &lt;/span&gt;열거할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있도록&lt;span&gt; &lt;/span&gt;합니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;이는&lt;span&gt; &lt;/span&gt;컬렉션의&lt;span&gt; &lt;/span&gt;요소를&lt;span&gt; &lt;/span&gt;순차적으로&lt;span&gt; &lt;/span&gt;접근하는&lt;span&gt; &lt;/span&gt;일반적인&lt;span&gt; &lt;/span&gt;인터페이스를&lt;span&gt; &lt;/span&gt;정의하고&lt;span&gt;, &lt;/span&gt;이&lt;span&gt; &lt;/span&gt;인터페이스를&lt;span&gt; &lt;/span&gt;구현한&lt;span&gt; &lt;/span&gt;반복자&lt;span&gt; &lt;/span&gt;객체를&lt;span&gt; &lt;/span&gt;사용하여&lt;span&gt; &lt;/span&gt;컬렉션의&lt;span&gt; &lt;/span&gt;요소에&lt;span&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 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;800&quot; data-origin-height=&quot;572&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NQKEE/btsF8bl1Ne2/7HYifGmINsQHWVkfwHAng0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NQKEE/btsF8bl1Ne2/7HYifGmINsQHWVkfwHAng0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NQKEE/btsF8bl1Ne2/7HYifGmINsQHWVkfwHAng0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNQKEE%2FbtsF8bl1Ne2%2F7HYifGmINsQHWVkfwHAng0%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;800&quot; height=&quot;572&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;572&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;옵서버 패턴( observer Pattern)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옵저버&lt;span&gt; &lt;/span&gt;패턴은&lt;span&gt; &lt;/span&gt;객체&lt;span&gt; &lt;/span&gt;간의&lt;span&gt; &lt;/span&gt;일대다&lt;span&gt; &lt;/span&gt;종속성을&lt;span&gt; &lt;/span&gt;정의하는&lt;span&gt; &lt;/span&gt;디자인&lt;span&gt; &lt;/span&gt;패턴입니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;이&lt;span&gt; &lt;/span&gt;패턴은&lt;span&gt; &lt;/span&gt;주로&lt;span&gt; &lt;/span&gt;상태나&lt;span&gt; &lt;/span&gt;데이터의&lt;span&gt; &lt;/span&gt;변화를&lt;span&gt; &lt;/span&gt;감지하고&lt;span&gt; &lt;/span&gt;이에&lt;span&gt; &lt;/span&gt;대응하는&lt;span&gt; &lt;/span&gt;행동을&lt;span&gt; &lt;/span&gt;수행할&lt;span&gt; &lt;/span&gt;때&lt;span&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 data-ke-size=&quot;size16&quot;&gt;프런트엔드 상태관리 라이브러리인 redu 툴은 observer 패턴을 기반으로 구현되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;참고로 zustand는 React의 ContextApi를 이용해 상태관리 제공&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;/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&gt;(Subject)&lt;/span&gt;와&lt;span&gt; &lt;/span&gt;구독자&lt;span&gt;(Observer)&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;나타내는&lt;span&gt; &lt;/span&gt;클래스를&lt;span&gt; &lt;/span&gt;구현하여&lt;span&gt; &lt;/span&gt;이벤트&lt;span&gt; &lt;/span&gt;발생&lt;span&gt; &lt;/span&gt;시&lt;span&gt; &lt;/span&gt;구독자들에게&lt;span&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 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;Subject 인터페이스는 주제(Subject) 역할을 정의하고, 구독자 관리와 알림을 위한 메소드를 포함합니다.&lt;/li&gt;
&lt;li&gt;Observer 인터페이스는 구독자(Observer) 역할을 정의하고, 주제로부터 업데이트를 받기 위한 update 메소드를 포함합니다.&lt;/li&gt;
&lt;li&gt;ConcreteSubject 클래스는 실제 주제를 구현하며, 상태 변경 시 등록된 모든 구독자에게 알림을 보냅니다.&lt;/li&gt;
&lt;li&gt;&lt;span&gt;ConcreteObserver &lt;/span&gt;클래스는&lt;span&gt; &lt;/span&gt;실제&lt;span&gt; &lt;/span&gt;구독자를&lt;span&gt; &lt;/span&gt;구현하며&lt;span&gt;, &lt;/span&gt;주제로부터&lt;span&gt; &lt;/span&gt;메시지를&lt;span&gt; &lt;/span&gt;받아&lt;span&gt; &lt;/span&gt;출력합니다&lt;span&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1711633247643&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 주제(Subject) 인터페이스
interface Subject {
    attach(observer: Observer): void;
    detach(observer: Observer): void;
    notify(): void;
}

// 구독자(Observer) 인터페이스
interface Observer {
    update(message: any): void;
}

// 구체적인 주제 클래스
class ConcreteSubject implements Subject {
    private observers: Observer[] = [];
    private state: any;

    getState(): any {
        return this.state;
    }

    setState(state: any): void {
        this.state = state;
        this.notify();
    }

    attach(observer: Observer): void {
        this.observers.push(observer);
    }

    detach(observer: Observer): void {
        const index = this.observers.indexOf(observer);
        if (index !== -1) {
            this.observers.splice(index, 1);
        }
    }

    notify(): void {
        for (const observer of this.observers) {
            observer.update(this.state);
        }
    }
}

// 구체적인 구독자 클래스
class ConcreteObserver implements Observer {
    update(message: any): void {
        console.log(&quot;Received message:&quot;, message);
    }
}

// 테스트
const subject = new ConcreteSubject();
const observer1 = new ConcreteObserver();
const observer2 = new ConcreteObserver();

// 구독자들을 주제에 등록
subject.attach(observer1);
subject.attach(observer2);

// 상태 변경 시 모든 구독자들에게 알림
subject.setState(&quot;New state!&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;511&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQ3LE8/btsGbWJetVS/3Jvq48SnMUpBYNqiEcr2t1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQ3LE8/btsGbWJetVS/3Jvq48SnMUpBYNqiEcr2t1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQ3LE8/btsGbWJetVS/3Jvq48SnMUpBYNqiEcr2t1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQ3LE8%2FbtsGbWJetVS%2F3Jvq48SnMUpBYNqiEcr2t1%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;800&quot; height=&quot;511&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;511&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;구조 패턴( Structural Pattern)&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스나&lt;span&gt; &lt;/span&gt;객체들&lt;span&gt; &lt;/span&gt;사이의&lt;span&gt; &lt;/span&gt;관계를&lt;span&gt; &lt;/span&gt;강화하고&lt;span&gt; &lt;/span&gt;구성하는&lt;span&gt; &lt;/span&gt;방법을&lt;span&gt; &lt;/span&gt;제공하여&lt;span&gt; &lt;/span&gt;코드의&lt;span&gt; &lt;/span&gt;유지보수성&lt;span&gt;, &lt;/span&gt;재사용성&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;데코레이터 패턴(Decorator Pattern)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;객체에&lt;span&gt; &lt;/span&gt;동적으로&lt;span&gt; &lt;/span&gt;새로운&lt;span&gt; &lt;/span&gt;기능을&lt;span&gt; &lt;/span&gt;추가하는&lt;span&gt; &lt;/span&gt;패턴&lt;/b&gt;입니다&lt;span&gt;. &lt;/span&gt;이&lt;span&gt; &lt;/span&gt;패턴은&lt;span&gt; &lt;/span&gt;상속을&lt;span&gt; &lt;/span&gt;사용하지&lt;span&gt; &lt;/span&gt;않고도&lt;span&gt; &lt;/span&gt;객체의&lt;span&gt; &lt;/span&gt;기능을&lt;span&gt; &lt;/span&gt;확장할&lt;span&gt; &lt;/span&gt;수&lt;span&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;/p&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&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&gt; &lt;/span&gt;주문&lt;span&gt; &lt;/span&gt;시&lt;span&gt; &lt;/span&gt;커피에&lt;span&gt; &lt;/span&gt;여러&lt;span&gt; &lt;/span&gt;가지&lt;span&gt; &lt;/span&gt;토핑을&lt;span&gt; &lt;/span&gt;추가하는&lt;span&gt; &lt;/span&gt;상황을&lt;span&gt; &lt;/span&gt;가정하겠습니다&lt;span&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;Coffee 인터페이스는 기본 커피의 동작을 정의합니다.&lt;/li&gt;
&lt;li&gt;SimpleCoffee 클래스는 기본 커피를 구현합니다.&lt;/li&gt;
&lt;li&gt;CoffeeDecorator 추상 클래스는 데코레이터의 기본 구조를 정의합니다.&lt;/li&gt;
&lt;li&gt;MilkDecorator&lt;span&gt;와&lt;/span&gt; WhippedCreamDecorator &lt;span&gt;클래스는&lt;/span&gt; &lt;span&gt;각각&lt;/span&gt; &lt;span&gt;우유와&lt;/span&gt; &lt;span&gt;휘핑&lt;/span&gt; &lt;span&gt;크림을&lt;/span&gt; &lt;span&gt;추가하는&lt;/span&gt; &lt;span&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;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1711633514828&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 커피 인터페이스
interface Coffee {
    cost(): number;
    getDescription(): string;
}

// 기본 커피 클래스
class SimpleCoffee implements Coffee {
    cost(): number {
        return 5;
    }

    getDescription(): string {
        return &quot;Simple Coffee&quot;;
    }
}

// 데코레이터 클래스
abstract class CoffeeDecorator implements Coffee {
    protected decoratedCoffee: Coffee;

    constructor(coffee: Coffee) {
        this.decoratedCoffee = coffee;
    }

    cost(): number {
        return this.decoratedCoffee.cost();
    }

    getDescription(): string {
        return this.decoratedCoffee.getDescription();
    }
}

// 토핑 데코레이터 - 우유
class MilkDecorator extends CoffeeDecorator {
    constructor(coffee: Coffee) {
        super(coffee);
    }

    cost(): number {
        return super.cost() + 2;
    }

    getDescription(): string {
        return super.getDescription() + &quot;, Milk&quot;;
    }
}

// 토핑 데코레이터 - 휘핑 크림
class WhippedCreamDecorator extends CoffeeDecorator {
    constructor(coffee: Coffee) {
        super(coffee);
    }

    cost(): number {
        return super.cost() + 3;
    }

    getDescription(): string {
        return super.getDescription() + &quot;, Whipped Cream&quot;;
    }
}

// 테스트
let coffee: Coffee = new SimpleCoffee();
console.log(coffee.getDescription(), &quot;costs&quot;, coffee.cost());

coffee = new MilkDecorator(coffee);
console.log(coffee.getDescription(), &quot;costs&quot;, coffee.cost());

coffee = new WhippedCreamDecorator(coffee);
console.log(coffee.getDescription(), &quot;costs&quot;, coffee.cost());&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;639&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1L2G8/btsGa9I38B6/vlk1PDE7SNBQMDabr47Pw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1L2G8/btsGa9I38B6/vlk1PDE7SNBQMDabr47Pw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1L2G8/btsGa9I38B6/vlk1PDE7SNBQMDabr47Pw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1L2G8%2FbtsGa9I38B6%2Fvlk1PDE7SNBQMDabr47Pw1%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;800&quot; height=&quot;639&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;639&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;프록시 패턴(Proxy Pattern)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한&lt;span&gt; &lt;/span&gt;객체에&lt;span&gt; &lt;/span&gt;대한&lt;span&gt; &lt;/span&gt;접근을&lt;span&gt; &lt;/span&gt;제어하거나&lt;span&gt; &lt;/span&gt;대리자&lt;span&gt; &lt;/span&gt;역할을&lt;span&gt; &lt;/span&gt;하는&lt;span&gt; &lt;/span&gt;객체를&lt;span&gt; &lt;/span&gt;제공하여&lt;span&gt; &lt;/span&gt;추가적인&lt;span&gt; &lt;/span&gt;기능을&lt;span&gt; &lt;/span&gt;제공하거나&lt;span&gt; &lt;/span&gt;제어하는&lt;span&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 data-ke-size=&quot;size18&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;이미지 로딩을 지연시키는 프록시를 구현해보겠습니다.&lt;/p&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;Image 인터페이스는 이미지의 기본 동작을 정의합니다.&lt;/li&gt;
&lt;li&gt;RealImage 클래스는 실제 이미지를 로딩하고 표시합니다.&lt;/li&gt;
&lt;li&gt;&lt;span&gt;ImageProxy &lt;/span&gt;클래스는&lt;span&gt; &lt;/span&gt;실제&lt;span&gt; &lt;/span&gt;이미지를&lt;span&gt; &lt;/span&gt;로딩하기&lt;span&gt; &lt;/span&gt;전까지는&lt;span&gt; &lt;/span&gt;실제&lt;span&gt; &lt;/span&gt;이미지를&lt;span&gt; &lt;/span&gt;생성하지&lt;span&gt; &lt;/span&gt;않습니다&lt;span&gt;. &lt;/span&gt;대신&lt;span&gt;, &lt;/span&gt;이미지가&lt;span&gt; &lt;/span&gt;요청될&lt;span&gt; &lt;/span&gt;때마다&lt;span&gt; &lt;/span&gt;실제&lt;span&gt; &lt;/span&gt;이미지를&lt;span&gt; &lt;/span&gt;로딩하여&lt;span&gt; &lt;/span&gt;표시합니다&lt;span&gt;.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1711633567419&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 이미지 인터페이스
interface Image {
    display(): void;
}

// 실제 이미지 클래스
class RealImage implements Image {
    private filename: string;

    constructor(filename: string) {
        this.filename = filename;
        this.loadFromDisk();
    }

    private loadFromDisk(): void {
        console.log(&quot;Loading image:&quot;, this.filename);
    }

    display(): void {
        console.log(&quot;Displaying image:&quot;, this.filename);
    }
}

// 이미지 프록시 클래스
class ImageProxy implements Image {
    private filename: string;
    private realImage: RealImage | null;

    constructor(filename: string) {
        this.filename = filename;
        this.realImage = null;
    }

    display(): void {
        if (!this.realImage) {
            this.realImage = new RealImage(this.filename);
        }
        this.realImage.display();
    }
}

// 테스트
const image1: Image = new ImageProxy(&quot;image1.jpg&quot;);
const image2: Image = new ImageProxy(&quot;image2.jpg&quot;);

// 이미지 1은 처음에 로딩이 발생
image1.display();
// 이미지 1은 두 번째 호출부터 로딩이 발생하지 않음
image1.display();
// 이미지 2는 처음에 로딩이 발생
image2.display();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;493&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dk8Uir/btsGadSI631/mqCNgmkWZSvChntxkPO7i1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dk8Uir/btsGadSI631/mqCNgmkWZSvChntxkPO7i1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dk8Uir/btsGadSI631/mqCNgmkWZSvChntxkPO7i1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdk8Uir%2FbtsGadSI631%2FmqCNgmkWZSvChntxkPO7i1%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;800&quot; height=&quot;493&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;493&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;어댑터 패턴(Proxy Pattern)&lt;br /&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;서로&lt;span&gt; &lt;/span&gt;다른&lt;span&gt; &lt;/span&gt;인터페이스를&lt;span&gt; &lt;/span&gt;가진&lt;span&gt; &lt;/span&gt;두&lt;span&gt; &lt;/span&gt;개의&lt;span&gt; &lt;/span&gt;클래스를&lt;span&gt; &lt;/span&gt;함께&lt;span&gt; &lt;/span&gt;작동할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있도록&lt;span&gt; &lt;/span&gt;변환&lt;/b&gt;하는&lt;span&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;b&gt;기존의&lt;span&gt; &lt;/span&gt;코드를&lt;span&gt; &lt;/span&gt;수정하지&lt;span&gt; &lt;/span&gt;않고도&lt;span&gt; &lt;/span&gt;새로운&lt;span&gt; &lt;/span&gt;인터페이스에&lt;span&gt; &lt;/span&gt;맞춰&lt;span&gt; &lt;/span&gt;사용&lt;/b&gt;할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있도록&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&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&gt; &lt;/span&gt;변환하여&lt;span&gt; &lt;/span&gt;다른&lt;span&gt; &lt;/span&gt;지역에서도&lt;span&gt; &lt;/span&gt;사용할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있는&lt;span&gt; &lt;/span&gt;장비를&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;코드&lt;/span&gt;&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1711633756423&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 한국 콘센트 인터페이스
interface KoreanPlug {
    supplyPower(): void;
}

// 한국 콘센트 구현 클래스
class KoreanSocket implements KoreanPlug {
    supplyPower(): void {
        console.log(&quot;Korean plug is supplying power.&quot;);
    }
}

// 미국 콘센트 인터페이스
interface USPlug {
    provideElectricity(): void;
}

// 미국 콘센트 구현 클래스
class USASocket implements USPlug {
    provideElectricity(): void {
        console.log(&quot;US plug is providing electricity.&quot;);
    }
}

// 어댑터 클래스
class KoreanToUSAdapter implements USPlug {
    private koreanPlug: KoreanPlug;

    constructor(koreanPlug: KoreanPlug) {
        this.koreanPlug = koreanPlug;
    }

    provideElectricity(): void {
        console.log(&quot;Adapter is converting Korean plug to US plug.&quot;);
        this.koreanPlug.supplyPower();
    }
}

// 테스트
const koreanPlug: KoreanPlug = new KoreanSocket();
const adapter: USPlug = new KoreanToUSAdapter(koreanPlug);

adapter.provideElectricity();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;301&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bnFnpc/btsGadrDEw8/JVErz5X3uZ1abxNDwWWvFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bnFnpc/btsGadrDEw8/JVErz5X3uZ1abxNDwWWvFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bnFnpc/btsGadrDEw8/JVErz5X3uZ1abxNDwWWvFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbnFnpc%2FbtsGadrDEw8%2FJVErz5X3uZ1abxNDwWWvFK%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;800&quot; height=&quot;301&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;301&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/h4&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;파사드 패턴(Proxy Pattern)&lt;/span&gt;&lt;/h4&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;span&gt; &lt;/span&gt;서브시스템의&lt;span&gt; &lt;/span&gt;인터페이스를&lt;span&gt; &lt;/span&gt;단순화&lt;/b&gt;시켜&lt;span&gt; &lt;/span&gt;사용자에게&lt;span&gt; &lt;/span&gt;&lt;b&gt;더&lt;span&gt; &lt;/span&gt;쉽게&lt;span&gt; &lt;/span&gt;접근할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있도록&lt;span&gt; &lt;/span&gt;하는&lt;span&gt; &lt;/span&gt;패턴&lt;/b&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;/span&gt;클라이언트는&lt;span&gt; &lt;/span&gt;복잡한&lt;span&gt; &lt;/span&gt;서브시스템을&lt;span&gt; &lt;/span&gt;직접&lt;span&gt; &lt;/span&gt;다루지&lt;span&gt; &lt;/span&gt;않고도&lt;span&gt; &lt;/span&gt;사용할&lt;span&gt; &lt;/span&gt;수&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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&gt; &lt;/span&gt;부팅하는&lt;span&gt; &lt;/span&gt;과정을&lt;span&gt; &lt;/span&gt;파사드&lt;span&gt; &lt;/span&gt;패턴을&lt;span&gt; &lt;/span&gt;사용하여&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU, Memory, Display 클래스는 각각 CPU, 메모리, 디스플레이의 동작을 구현합니다.&lt;/li&gt;
&lt;li&gt;ComputerFacade 클래스는 이러한 서브시스템을 간단한 인터페이스로 묶어줍니다. startComputer 메서드를 통해 클라이언트는 컴퓨터를 부팅할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;span&gt;클라이언트&lt;/span&gt; &lt;span&gt;코드에서는&lt;/span&gt; ComputerFacade &lt;span&gt;인스턴스를&lt;/span&gt; &lt;span&gt;생성하고&lt;/span&gt; startComputer &lt;span&gt;메서드를&lt;/span&gt; &lt;span&gt;호출하여&lt;/span&gt; &lt;span&gt;컴퓨터를&lt;/span&gt; &lt;span&gt;부팅합니다&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;pre id=&quot;code_1711633802270&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// CPU 클래스
class CPU {
    public bootUp(): void {
        console.log(&quot;CPU is booting up...&quot;);
    }
}

// 메모리 클래스
class Memory {
    public load(): void {
        console.log(&quot;Memory is loading...&quot;);
    }
}

// 디스플레이 클래스
class Display {
    public displayImage(): void {
        console.log(&quot;Displaying image...&quot;);
    }
}

// 파사드 클래스
class ComputerFacade {
    private cpu: CPU;
    private memory: Memory;
    private display: Display;

    constructor() {
        this.cpu = new CPU();
        this.memory = new Memory();
        this.display = new Display();
    }

    public startComputer(): void {
        console.log(&quot;Starting computer...&quot;);
        this.cpu.bootUp();
        this.memory.load();
        this.display.displayImage();
        console.log(&quot;Computer started.&quot;);
    }
}

// 클라이언트 코드
const computerFacade = new ComputerFacade();
computerFacade.startComputer();&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&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;size18&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://m.hanbit.co.kr/channel/category/category_view.html?cms_code=CMS8616098823&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://m.hanbit.co.kr/channel/category/category_view.html?cms_code=CMS8616098823&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>cs</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/215</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%95%8C%EC%95%84%EB%91%90%EB%A9%B4-%EC%93%B8%EB%8D%B0-%EC%9E%88%EB%8A%94-GOF-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4#entry215comment</comments>
      <pubDate>Thu, 28 Mar 2024 22:50:31 +0900</pubDate>
    </item>
    <item>
      <title>Node.js 메모리 누수(feat. SSR)</title>
      <link>https://hmk1022.tistory.com/entry/Nodejs-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%88%84%EC%88%98feat-SSR</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&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;- Node.js 환경이든 브라우저 환경이든&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; 크롬 브라우저의 Memory 탭에서 메모리 누수의 범인을 찾을 수 있음!&lt;/p&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;메모리 누수(Memory Leak)이란?&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;메모리를 계속 차지하고 있는 현상&lt;/p&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;메모리 누수가 있으면 뭐가 문제일까?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JS를 동작시킬 메모리가 부족하니까, 성능이 좋지 않게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- GC의 활동이 늘어나면, CPU 사용량이 늘어난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- CPU intensive한 작업이 늘어나면, 이벤트 루프가 블로킹되서 연산이 느려진다.&lt;/p&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;띄워놓은 Node.js 서버가 죽는다.&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;a href=&quot;https://3-stack.tistory.com/10&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;SIGABRT&lt;/a&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;- 로드밸런서가 HTTP Status 502(Bad Gateway) 에러를 뱉을 수 있어요&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;메모리 누수 해결방법은?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 힙메모리를 늘려주거나 =&amp;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;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;메모리 누수가 있는지 어떻게 알 수 있을까?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/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-origin-width=&quot;861&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SzGhj/btsF3EhqvVf/qxVCh0WUku7wXGCV4vpVZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SzGhj/btsF3EhqvVf/qxVCh0WUku7wXGCV4vpVZk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SzGhj/btsF3EhqvVf/qxVCh0WUku7wXGCV4vpVZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSzGhj%2FbtsF3EhqvVf%2FqxVCh0WUku7wXGCV4vpVZk%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;861&quot; height=&quot;416&quot; data-origin-width=&quot;861&quot; data-origin-height=&quot;416&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;h4 data-ke-size=&quot;size20&quot;&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;372&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLHfJw/btsF3VwCWhc/EOZR0rasfrvVkFO08OWTMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cLHfJw/btsF3VwCWhc/EOZR0rasfrvVkFO08OWTMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cLHfJw/btsF3VwCWhc/EOZR0rasfrvVkFO08OWTMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcLHfJw%2FbtsF3VwCWhc%2FEOZR0rasfrvVkFO08OWTMk%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;326&quot; height=&quot;372&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;372&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;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;h4 data-ke-size=&quot;size20&quot;&gt;메모리 누수가 발생하는 코드는 모니터링 도구에서 어떻게 보일까?&lt;/h4&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;- 요청을 받으면 응답을 내려주고 200 status를 내려주는 node.js 코드&lt;/p&gt;
&lt;pre id=&quot;code_1711289828784&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const server = http.createServer((req, res) =&amp;gt; {
	res.writeHead(200, {'Content-Type': 'text/html'});
    res.write(`
    	&amp;lt;!DOCTYPE html&amp;gt;
        &amp;lt;html lang=&quot;en&quot;&amp;gt;
            &amp;lt;head&amp;gt;
		&amp;lt;title&amp;gt;Hello World&amp;lt;/title&amp;gt;
            &amp;lt;/head&amp;gt;
            &amp;lt;body&amp;gt;
            	&amp;lt;h1&amp;gt;Content&amp;lt;/h1&amp;gt;
            &amp;lt;/body&amp;gt;
	&amp;lt;/html&amp;gt;
    `);
    
    res.end();
})&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;SSR 이면서 유저의 트래픽을 받는 상황을 재현하기 위해&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;825&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BWKAL/btsF4yOOCnZ/ZrqqqHvr2iKK544phfkBE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BWKAL/btsF4yOOCnZ/ZrqqqHvr2iKK544phfkBE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BWKAL/btsF4yOOCnZ/ZrqqqHvr2iKK544phfkBE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBWKAL%2FbtsF4yOOCnZ%2FZrqqqHvr2iKK544phfkBE0%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;825&quot; height=&quot;450&quot; data-origin-width=&quot;825&quot; data-origin-height=&quot;450&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;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;&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;873&quot; data-origin-height=&quot;351&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/82rdy/btsF1utOSaQ/m3LKPeK5RNAGQ86geaOPP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/82rdy/btsF1utOSaQ/m3LKPeK5RNAGQ86geaOPP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/82rdy/btsF1utOSaQ/m3LKPeK5RNAGQ86geaOPP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F82rdy%2FbtsF1utOSaQ%2Fm3LKPeK5RNAGQ86geaOPP0%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;873&quot; height=&quot;351&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;351&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;- 백만번의 반복문을 돌려 listItems에 i 값을 push&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;182&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8J0ps/btsF3mgXfQi/Roso33q3n7FWFVcUwvNk9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8J0ps/btsF3mgXfQi/Roso33q3n7FWFVcUwvNk9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8J0ps/btsF3mgXfQi/Roso33q3n7FWFVcUwvNk9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8J0ps%2FbtsF3mgXfQi%2FRoso33q3n7FWFVcUwvNk9K%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;443&quot; height=&quot;182&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;182&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;52&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DHip7/btsF2uGCw01/ByYRucYOKM5JzhyetYkvAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DHip7/btsF2uGCw01/ByYRucYOKM5JzhyetYkvAK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DHip7/btsF2uGCw01/ByYRucYOKM5JzhyetYkvAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDHip7%2FbtsF2uGCw01%2FByYRucYOKM5JzhyetYkvAK%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;52&quot; data-origin-width=&quot;626&quot; data-origin-height=&quot;52&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;501&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c0qXY7/btsF1MnsSnB/9EL8Jw5uAMsfBKVttIIFFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c0qXY7/btsF1MnsSnB/9EL8Jw5uAMsfBKVttIIFFk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c0qXY7/btsF1MnsSnB/9EL8Jw5uAMsfBKVttIIFFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc0qXY7%2FbtsF1MnsSnB%2F9EL8Jw5uAMsfBKVttIIFFk%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;887&quot; height=&quot;501&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;501&quot;/&gt;&lt;/span&gt;&lt;/figure&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;&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-origin-width=&quot;859&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4qhQ0/btsF3eQOgYJ/814a2sC37vSjThKwgisPj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4qhQ0/btsF3eQOgYJ/814a2sC37vSjThKwgisPj1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4qhQ0/btsF3eQOgYJ/814a2sC37vSjThKwgisPj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4qhQ0%2FbtsF3eQOgYJ%2F814a2sC37vSjThKwgisPj1%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;859&quot; height=&quot;420&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;420&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&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;&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;b&gt;listItems변수를 전역변수로 선언했음&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;409&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/boUtxY/btsF4Zr2YlM/qU57FnxGeTY8dB4n2reXC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/boUtxY/btsF4Zr2YlM/qU57FnxGeTY8dB4n2reXC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/boUtxY/btsF4Zr2YlM/qU57FnxGeTY8dB4n2reXC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FboUtxY%2FbtsF4Zr2YlM%2FqU57FnxGeTY8dB4n2reXC1%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;855&quot; height=&quot;409&quot; data-origin-width=&quot;855&quot; data-origin-height=&quot;409&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;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;887&quot; data-origin-height=&quot;495&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blJSrY/btsF4yVALdh/6corURELuUqxay4Ko57K31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blJSrY/btsF4yVALdh/6corURELuUqxay4Ko57K31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blJSrY/btsF4yVALdh/6corURELuUqxay4Ko57K31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblJSrY%2FbtsF4yVALdh%2F6corURELuUqxay4Ko57K31%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;887&quot; height=&quot;495&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;495&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;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;884&quot; data-origin-height=&quot;493&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/okdo3/btsF3mabFMD/6KwXscTZV6XD1GaKa9ZmS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/okdo3/btsF3mabFMD/6KwXscTZV6XD1GaKa9ZmS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/okdo3/btsF3mabFMD/6KwXscTZV6XD1GaKa9ZmS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fokdo3%2FbtsF3mabFMD%2F6KwXscTZV6XD1GaKa9ZmS0%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;884&quot; height=&quot;493&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;493&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;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;884&quot; data-origin-height=&quot;495&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IfuZx/btsF1CFl9O9/JNDOJOfYMCJR4aJbpq0UH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IfuZx/btsF1CFl9O9/JNDOJOfYMCJR4aJbpq0UH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IfuZx/btsF1CFl9O9/JNDOJOfYMCJR4aJbpq0UH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIfuZx%2FbtsF1CFl9O9%2FJNDOJOfYMCJR4aJbpq0UH0%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;884&quot; height=&quot;495&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;495&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;메모리 누수를 해결해보자!&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;793&quot; data-origin-height=&quot;373&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NgUez/btsF2S8gFqN/8CGcfyc885H32q6rLhSnH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NgUez/btsF2S8gFqN/8CGcfyc885H32q6rLhSnH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NgUez/btsF2S8gFqN/8CGcfyc885H32q6rLhSnH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNgUez%2FbtsF2S8gFqN%2F8CGcfyc885H32q6rLhSnH0%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;793&quot; height=&quot;373&quot; data-origin-width=&quot;793&quot; data-origin-height=&quot;373&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;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;&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;그전에 간략하게 V8이 메모리를 관리하는 방식을 알아보자&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;V8은 GC 알고리즘으로 Mark and Sweep 방식을 주로 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단히 말해서, 사용하는 것은 Mark 사용하지 않는 것은 Sweep(치워버림) 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;414&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TQMgi/btsF3cFtF4m/xW5GpQpStUvx4c7jlKrSc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TQMgi/btsF3cFtF4m/xW5GpQpStUvx4c7jlKrSc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TQMgi/btsF3cFtF4m/xW5GpQpStUvx4c7jlKrSc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTQMgi%2FbtsF3cFtF4m%2FxW5GpQpStUvx4c7jlKrSc0%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;786&quot; height=&quot;414&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;414&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;p data-ke-size=&quot;size16&quot;&gt;원시타입이 아닌(array, object, function- js는 함수도 일급객체 등등..) &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;사용하는 것은 mark 아닌것은&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GC가 한번 돌면서 불필요한 객체를 수거해서 Sweep!&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;804&quot; data-origin-height=&quot;350&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcVugL/btsF2RuJO2x/XLqaxeYrSAr6IAh2B91leK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcVugL/btsF2RuJO2x/XLqaxeYrSAr6IAh2B91leK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcVugL/btsF2RuJO2x/XLqaxeYrSAr6IAh2B91leK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcVugL%2FbtsF2RuJO2x%2FXLqaxeYrSAr6IAh2B91leK%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;804&quot; height=&quot;350&quot; data-origin-width=&quot;804&quot; data-origin-height=&quot;350&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;h4 data-ke-size=&quot;size20&quot;&gt;GC에 의해 정리되지 않고 계속해서 메모리가 살아남아 있다면?&amp;nbsp;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;V8은 힙메모리를 관리하기 위해 영역을 나눠서 관리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 Young Generation과 Old Generation으로 나눠져 있고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GC도 Minor와 Major로 나눠져 있습니다.&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;824&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bkyKa3/btsF3ddjMwC/P51HFvxkKildQ8JhIAEVR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bkyKa3/btsF3ddjMwC/P51HFvxkKildQ8JhIAEVR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkyKa3/btsF3ddjMwC/P51HFvxkKildQ8JhIAEVR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbkyKa3%2FbtsF3ddjMwC%2FP51HFvxkKildQ8JhIAEVR1%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;824&quot; height=&quot;456&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;456&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;p data-ke-size=&quot;size16&quot;&gt;처음 선언한 객체가 있다면 nursery(유아기) 영역에 해당되는 곳에 메모리가 할당되게 된다.&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;850&quot; data-origin-height=&quot;469&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yv61f/btsF1A8x1d9/54uufvbmcOdOhkK4skVE8k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yv61f/btsF1A8x1d9/54uufvbmcOdOhkK4skVE8k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yv61f/btsF1A8x1d9/54uufvbmcOdOhkK4skVE8k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fyv61f%2FbtsF1A8x1d9%2F54uufvbmcOdOhkK4skVE8k%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;850&quot; height=&quot;469&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;469&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;p data-ke-size=&quot;size16&quot;&gt;그리고 GC가 한번 돌고 해당 메모리가 살아있다면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중간기에 해당하는 intermediate로 넘어가게 됩니다.&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;831&quot; data-origin-height=&quot;449&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O4IyM/btsF4VJXdjk/Ykjk3Yt5tdkkjgPxQ3dRKK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O4IyM/btsF4VJXdjk/Ykjk3Yt5tdkkjgPxQ3dRKK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O4IyM/btsF4VJXdjk/Ykjk3Yt5tdkkjgPxQ3dRKK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO4IyM%2FbtsF4VJXdjk%2FYkjk3Yt5tdkkjgPxQ3dRKK%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;831&quot; height=&quot;449&quot; data-origin-width=&quot;831&quot; data-origin-height=&quot;449&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;두 번째에도 GC에서 살아남았다?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Old Generation으로 가게된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;V8 문서를 살펴보게 되면 Old Generation 영역까지 살아남은 메모리는 거의없다! 라고 나와 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;832&quot; data-origin-height=&quot;451&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFz3yd/btsF1JdcRlY/oyM3MHAuac78ozjP5BkqZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFz3yd/btsF1JdcRlY/oyM3MHAuac78ozjP5BkqZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFz3yd/btsF1JdcRlY/oyM3MHAuac78ozjP5BkqZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFz3yd%2FbtsF1JdcRlY%2FoyM3MHAuac78ozjP5BkqZ0%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;832&quot; height=&quot;451&quot; data-origin-width=&quot;832&quot; data-origin-height=&quot;451&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;b&gt;Nursey:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;처음 Object이 할당된 공간&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Intermeditate&lt;/b&gt;: 첫 GC에서 살아남아 이동한 공간&lt;/p&gt;
&lt;p style=&quot;color: #555555; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Old Generation:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;두 번째 GC에서 살아남아 이동한 공간&lt;/p&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;Old Generation이 꽉찬 상태가된다?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; 서버가 죽는다! 꿱!&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;839&quot; data-origin-height=&quot;462&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckwQeF/btsF2DKeCqh/ZnNTHmqtMjvY3MuHwcb8f1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckwQeF/btsF2DKeCqh/ZnNTHmqtMjvY3MuHwcb8f1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckwQeF/btsF2DKeCqh/ZnNTHmqtMjvY3MuHwcb8f1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckwQeF%2FbtsF2DKeCqh%2FZnNTHmqtMjvY3MuHwcb8f1%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;839&quot; height=&quot;462&quot; data-origin-width=&quot;839&quot; data-origin-height=&quot;462&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;p data-ke-size=&quot;size16&quot;&gt;전역으로 선언된 listItems는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;함수안에서 계속해서 참조하기 때문&lt;/b&gt;에 Old Generation 영역으로 이동하게 될 것 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요청이 올 수록 계속해서 GC에 의해 수거되지 않고 메모리 영역을 계속해서 커집니다!&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;830&quot; data-origin-height=&quot;461&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AcubH/btsF4WvjRPV/sC8ipXCYK43mFo7IRIpOdK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AcubH/btsF4WvjRPV/sC8ipXCYK43mFo7IRIpOdK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AcubH/btsF4WvjRPV/sC8ipXCYK43mFo7IRIpOdK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAcubH%2FbtsF4WvjRPV%2FsC8ipXCYK43mFo7IRIpOdK%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;830&quot; height=&quot;461&quot; data-origin-width=&quot;830&quot; data-origin-height=&quot;461&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;size18&quot;&gt;그렇다면 힙 메모리를 늘려주면 메모리 누수가 사라질까? =&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;단순하게 구글링을 하게되면 아래와 같이 해결법이 나온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Node.js 메모리 부족 어떻게 해결함?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; --max-old-space-size 고고&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgHTvU/btsF2Ny9Ucx/tgvpXBkBsIlmrE3jisFEh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgHTvU/btsF2Ny9Ucx/tgvpXBkBsIlmrE3jisFEh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgHTvU/btsF2Ny9Ucx/tgvpXBkBsIlmrE3jisFEh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgHTvU%2FbtsF2Ny9Ucx%2FtgvpXBkBsIlmrE3jisFEh1%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;824&quot; height=&quot;424&quot; data-origin-width=&quot;824&quot; data-origin-height=&quot;424&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;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;--max-old-space-size 는 Old Generation(Old Space) 영역&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;--max- semi-space-size * 3 는  Young Generation(New Space) 영역&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;843&quot; data-origin-height=&quot;475&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mbbDh/btsF40YNBfO/1RSk7S4tOdtxQxuMfEnOh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mbbDh/btsF40YNBfO/1RSk7S4tOdtxQxuMfEnOh1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mbbDh/btsF40YNBfO/1RSk7S4tOdtxQxuMfEnOh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmbbDh%2FbtsF40YNBfO%2F1RSk7S4tOdtxQxuMfEnOh1%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;475&quot; data-origin-width=&quot;843&quot; data-origin-height=&quot;475&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;p data-ke-size=&quot;size18&quot;&gt;계속 살아남은 객체는 Old space로,&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;계속 힙메모리를 차지하면 OOM((Out of Memory)&lt;span&gt;은&lt;/span&gt; &lt;span&gt;시스템이&lt;/span&gt; &lt;span&gt;더&lt;/span&gt; &lt;span&gt;이상&lt;/span&gt; &lt;span&gt;메모리를&lt;/span&gt; &lt;span&gt;할당할&lt;/span&gt; &lt;span&gt;수&lt;/span&gt; &lt;span&gt;없을&lt;/span&gt; &lt;span&gt;때&lt;/span&gt; &lt;span&gt;발생하는&lt;/span&gt; &lt;span&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;&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;/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;1. 전역변수&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;2. 해제되지 않은 타이버(clearTimeout 등)&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;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;고로 메모리를 늘리는 것이 근본적인 해결법이 될 순 없다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;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;pre id=&quot;code_1711292332865&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;node --inspect index.js&lt;/code&gt;&lt;/pre&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;850&quot; data-origin-height=&quot;413&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kFTGw/btsF4zGYcRG/mniNM4HZzFoLbIKoFwSTS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kFTGw/btsF4zGYcRG/mniNM4HZzFoLbIKoFwSTS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kFTGw/btsF4zGYcRG/mniNM4HZzFoLbIKoFwSTS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkFTGw%2FbtsF4zGYcRG%2FmniNM4HZzFoLbIKoFwSTS1%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;850&quot; height=&quot;413&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;413&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;chrome에 inspect 옵션을 활용하는 방법도 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;568&quot; data-origin-height=&quot;395&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K9L1p/btsF3cMgvdd/JTRKHTY5eXXRpaTLyfLMg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K9L1p/btsF3cMgvdd/JTRKHTY5eXXRpaTLyfLMg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K9L1p/btsF3cMgvdd/JTRKHTY5eXXRpaTLyfLMg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK9L1p%2FbtsF3cMgvdd%2FJTRKHTY5eXXRpaTLyfLMg0%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;568&quot; height=&quot;395&quot; data-origin-width=&quot;568&quot; data-origin-height=&quot;395&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;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;b&gt;Reference&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=P3C7fzMqIYg&amp;amp;list=LL&amp;amp;index=12&amp;amp;t=343s&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=P3C7fzMqIYg&amp;amp;list=LL&amp;amp;index=12&amp;amp;t=343s&lt;/a&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;&lt;/p&gt;</description>
      <category>node</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/214</guid>
      <comments>https://hmk1022.tistory.com/entry/Nodejs-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%88%84%EC%88%98feat-SSR#entry214comment</comments>
      <pubDate>Mon, 25 Mar 2024 21:38:03 +0900</pubDate>
    </item>
    <item>
      <title>의도적 수련</title>
      <link>https://hmk1022.tistory.com/entry/%EC%9D%98%EB%8F%84%EC%A0%81-%EC%88%98%EB%A0%A8</link>
      <description>&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;&lt;br /&gt;&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;&lt;b&gt;업무를&amp;nbsp;하면서&amp;nbsp;빠르게&amp;nbsp;피드백받고&amp;nbsp;교정하면서&amp;nbsp;성장하는&amp;nbsp;&quot;애자일&amp;nbsp;철학&quot;이&amp;nbsp;필요하다.&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;span style=&quot;color: #9d9d9d;&quot;&gt;양치질을 30년 했다고 매일 똑같은 패턴, 강도로 반복만하니 양치질의 고수라고 하지 않는다.&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;&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;gt; 속도, 기존 로직 혹은 비즈니스 요구 파악, 이전에 쌓아 놨던 재사용성의 도움&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 안전성 있게, =&amp;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;&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;span style=&quot;color: #9d9d9d;&quot;&gt;- 함께자라기&lt;span&gt;&amp;nbsp;&lt;/span&gt;中&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>독서</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/213</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%9D%98%EB%8F%84%EC%A0%81-%EC%88%98%EB%A0%A8#entry213comment</comments>
      <pubDate>Sat, 23 Mar 2024 18:46:03 +0900</pubDate>
    </item>
    <item>
      <title>김프로의 회사생활 팁 feat. 개발자 (아주 중요하지만 아무도 안 알려주는)</title>
      <link>https://hmk1022.tistory.com/entry/%EA%B9%80%ED%94%84%EB%A1%9C%EC%9D%98-%ED%9A%8C%EC%82%AC%EC%83%9D%ED%99%9C-%ED%8C%81-feat-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%95%84%EC%A3%BC-%EC%A4%91%EC%9A%94%ED%95%98%EC%A7%80%EB%A7%8C-%EC%95%84%EB%AC%B4%EB%8F%84-%EC%95%88-%EC%95%8C%EB%A0%A4%EC%A3%BC%EB%8A%94</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;15년 차 정도되는 시니어 개발자분이 감사하게도,&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;&quot;어떤 사람이 일을 잘하는 사람인가?&quot;에 대한 개념이 잘 서지 않을 때마다 봐야겠다.&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;518&quot; data-origin-height=&quot;344&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IwiUZ/btsF1KP6RVc/nSVQDkllsKkVCbzKPohKFK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IwiUZ/btsF1KP6RVc/nSVQDkllsKkVCbzKPohKFK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IwiUZ/btsF1KP6RVc/nSVQDkllsKkVCbzKPohKFK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIwiUZ%2FbtsF1KP6RVc%2FnSVQDkllsKkVCbzKPohKFK%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;518&quot; height=&quot;344&quot; data-origin-width=&quot;518&quot; data-origin-height=&quot;344&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&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;/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;ex) 게이머&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 아마추어 : 시간이 날 때 틈틈이 즐긴다. 꼭 승리하지 않아도 즐거우면 OK&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;프로(의식)?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 몸값에 맞는 가치를 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;gt; 사장님 또는 고객은 쉽게 돈을 주지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;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;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;/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;- 살아남는 문제: 동물 vs 인간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;gt;&lt;span&gt;&amp;nbsp; 야생에서 동물은 어떻게 살아남는가&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;/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;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style8&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&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;/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;-....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style8&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&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;- 테스트를 어떻게 할지 개발하기 전에 고민한다.&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;gt; 자원 =&amp;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;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;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&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;같이 일했던 동료 중 좋았던 동료를 다른 회사에서도 찾게 되어있음&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;hr data-ke-style=&quot;style8&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&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;직업 시장에서 어떻게 살아남을 것인가&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;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&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;그 제품은 나의 걸어온 커리어를 대표하는 얼굴들이며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 마음가짐을 가지고 위에서 말했던, 프로자세로 나의 제품들을 만들어야겠다.&lt;/p&gt;</description>
      <category>TIL</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/212</guid>
      <comments>https://hmk1022.tistory.com/entry/%EA%B9%80%ED%94%84%EB%A1%9C%EC%9D%98-%ED%9A%8C%EC%82%AC%EC%83%9D%ED%99%9C-%ED%8C%81-feat-%EA%B0%9C%EB%B0%9C%EC%9E%90-%EC%95%84%EC%A3%BC-%EC%A4%91%EC%9A%94%ED%95%98%EC%A7%80%EB%A7%8C-%EC%95%84%EB%AC%B4%EB%8F%84-%EC%95%88-%EC%95%8C%EB%A0%A4%EC%A3%BC%EB%8A%94#entry212comment</comments>
      <pubDate>Fri, 22 Mar 2024 20:12:49 +0900</pubDate>
    </item>
    <item>
      <title>프론트엔드와 디자인 패턴</title>
      <link>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%99%80-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&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;디자인 패턴은 다음과 같은 주요 목적을 가지고 있습니다:&lt;br /&gt;&lt;br /&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;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;재사용성&lt;/b&gt;: 디자인 패턴은 특정 문제에 대한 해결책을 제공하므로, 해당 문제가 발생할 때마다 동일한 패턴을 재사용할 수 있습니다. 이를 통해 코드의 재사용성이 증가하고, 개발 시간과 비용을 절감할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;유지보수성&lt;/b&gt;: 디자인 패턴은 코드의 구조화를 도와주며, 코드의 의도를 명확하게 전달합니다. 이는 코드를 이해하고 유지보수하는 과정을 단순화하고 오류를 방지할 수 있도록 돕습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;확장성&lt;/b&gt;: 디자인 패턴은 변경 가능성이 높은 부분을 식별하고, 해당 부분을 분리하여 추상화함으로써 시스템의 확장성을 향상합니다. 새로운 요구사항이나 기능 추가 시에도 시스템을 유연하게 확장할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt; &lt;/span&gt;커뮤니케이션&lt;/b&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; &lt;/span&gt;패턴은&lt;span&gt; &lt;/span&gt;생성&lt;span&gt;(Creational), &lt;/span&gt;구조&lt;span&gt;(Structural), &lt;/span&gt;행위&lt;span&gt;(Behavioral) &lt;/span&gt;세&lt;span&gt; &lt;/span&gt;가지&lt;span&gt; &lt;/span&gt;범주로&lt;span&gt; &lt;/span&gt;나누어집니다&lt;span&gt;. &lt;/span&gt;&lt;b&gt;이러한&lt;span&gt; &lt;/span&gt;패턴들은&lt;span&gt; &lt;/span&gt;특정&lt;span&gt; &lt;/span&gt;문제&lt;span&gt; &lt;/span&gt;해결을&lt;span&gt; &lt;/span&gt;위해&lt;span&gt; &lt;/span&gt;공식화된&lt;span&gt; &lt;/span&gt;해결책을&lt;span&gt; &lt;/span&gt;제시하며&lt;span&gt;, &lt;/span&gt;이를&lt;span&gt; &lt;/span&gt;통해&lt;span&gt; &lt;/span&gt;소프트웨어의&lt;span&gt; &lt;/span&gt;품질을&lt;span&gt; &lt;/span&gt;향상시키고&lt;span&gt; &lt;/span&gt;개발&lt;span&gt; &lt;/span&gt;과정을&lt;span&gt; &lt;/span&gt;단순화&lt;/b&gt;합니다&lt;span&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;/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;수많은 애플리케이션, 소프트웨어가 있지만 FE의 관점에서 어떻게 발전해 왔고, 어떤 문제가 있었는지 작성했습니다.&lt;/p&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;MVC 디자인패턴&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;size18&quot;&gt;View&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Model&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 데이터 영역&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- javascript 메모리, 백엔드를 통해 받는 데이터, DB 등등의 소프트웨어의 데이터&lt;/p&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;Controller&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Model과 View 사이의 중간 역할&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Model의 데이터를 받아서 화면을 만듦, 사용자의 동작을 받아 Model을 변경&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;&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;800&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXXqMY/btsFR8Y88Om/6U7rZS1tSArsyKVYDAkgpK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXXqMY/btsFR8Y88Om/6U7rZS1tSArsyKVYDAkgpK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXXqMY/btsFR8Y88Om/6U7rZS1tSArsyKVYDAkgpK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXXqMY%2FbtsFR8Y88Om%2F6U7rZS1tSArsyKVYDAkgpK%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;800&quot; height=&quot;384&quot; data-origin-width=&quot;800&quot; data-origin-height=&quot;384&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;h4 data-ke-size=&quot;size20&quot;&gt;초창기의 웹 서비스의 MVC&lt;/h4&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;클라이언트단의 사양이 복잡해지고 SPA 등의 프론트엔드 프레임워크가 본격적으로 등장하면서 생기게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에는 프런트와 백엔드의 구분이 명확하지 않고, 웹사이트가 그 자체로 View의 역할을 수행하는 것으로 개발되었다.&lt;/p&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;Model - DB&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;View - HTML &amp;amp; CSS &amp;amp; JS&lt;br /&gt;&lt;span style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt;Controller - 라우터를 통해 데이터를 처리하고 새로운 HTML을 만들어서 보여주는 영역&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt; JQuery 등장 후 MVC&lt;/h4&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: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot;&gt; Model - ajax를 이용해 받아온 백엔드 데이터&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;View - HTML &amp;amp; CSS &amp;amp; JS&lt;br /&gt;&lt;span&gt;Controller - 사용자 입력을 처리하고 모델과 뷰 사이의 상호작용을 조정하여 UI 로직을 제어&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MVC를 최대한 분리해야 한다는 원칙에 맞게, HTML과 jQuery를 따로 관리하는 것이 이 패턴의 주요 포인트&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;단점&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- View를 업데이트하기 위해서 결국 Model과 View 사이의 의존성이 강해질 수 있고, 이는 규모가 커질수록 복잡성이 증가하게 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 데이터를 연동하고 받아오는 과정에서 반복적인 패턴이 자주 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Controller에 책임이 많아져 Controller에 부하가 생길 수 있음&lt;/p&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;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;&lt;b&gt;MVP 디자인패턴&lt;br /&gt;&lt;br /&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;422&quot; data-origin-height=&quot;608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cscFmJ/btsFV7Mkgqx/kEH2DcQKt8tNQKEKHR5Mm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cscFmJ/btsFV7Mkgqx/kEH2DcQKt8tNQKEKHR5Mm1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cscFmJ/btsFV7Mkgqx/kEH2DcQKt8tNQKEKHR5Mm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcscFmJ%2FbtsFV7Mkgqx%2FkEH2DcQKt8tNQKEKHR5Mm1%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;422&quot; height=&quot;608&quot; data-origin-width=&quot;422&quot; data-origin-height=&quot;608&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MVC 구조에서 View와 Model 간의 의존성을 해결하기 위해 제시된 모델이다. Controller 대신 Presenter가 생긴 구조로, 한때 Android 개발에서 가장 인기 있었던 구조라고 한다.&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;Model&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;View&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 데이터를 보여주는 방식을 정의&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 사용자의 action이 들어오면 presenter에게 전달&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;Presenter&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Model과 VIew 사이의 중계자 역할&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;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;View - Model 사이의 의존성 문제를 해결한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&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;View - Presenter&lt;span&gt;가&lt;/span&gt; 1:1&lt;span&gt;로&lt;/span&gt; &lt;span&gt;연결되면서&lt;/span&gt; View&lt;span&gt;와&lt;/span&gt; Presenter &lt;span&gt;사이의&lt;/span&gt; &lt;span&gt;의존성이&lt;/span&gt; &lt;span&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;&amp;nbsp;&lt;/p&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;&lt;b&gt;MVVM 디자인패턴&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;422&quot; data-origin-height=&quot;609&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qiX06/btsFV7r3NIC/KpY5kk2k7KStZWa42uTHRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qiX06/btsFV7r3NIC/KpY5kk2k7KStZWa42uTHRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qiX06/btsFV7r3NIC/KpY5kk2k7KStZWa42uTHRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqiX06%2FbtsFV7r3NIC%2FKpY5kk2k7KStZWa42uTHRk%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;422&quot; height=&quot;609&quot; data-origin-width=&quot;422&quot; data-origin-height=&quot;609&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;jQuery를 이용해 DOM을 직접 조장하는 방식에서, 템플릿과 바인딩을 통한 선언적 반식으로 변화하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MVC의 역할을 그대로이나 구현하는 방식이 바뀐 것에 가깝다고 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;FE 코드에서 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;이를 View를 그리는 Model만 신경 쓰게 되었다는 의미로 ViewModel이라고 부른다.&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;Model&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;View&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;ViewModel&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Model을 가지고 View를 그리는 역할이자, View가 Model과 상호작용할 수 있게 하는 역할,&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앵귤러 이후 React, Vue, Svelte 등 템플릿, 바인딩 문법의 차이가 조금씩 있을 뿐, MVVM이라는 아키텍처는 대부분&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;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;/li&gt;
&lt;li&gt;Model과 View의 관점을 분리하지 않고, 하나의 템플릿을 통해 관리하려는 방식으로 발전하게 된다.&lt;/li&gt;
&lt;li&gt;웹의&lt;span&gt; DOM api&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;잘&lt;span&gt; &lt;/span&gt;몰라도&lt;span&gt; &lt;/span&gt;비지니스&lt;span&gt; &lt;/span&gt;로직만으로&lt;span&gt; &lt;/span&gt;서비스를&lt;span&gt; &lt;/span&gt;만들&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있다&lt;span&gt;.&lt;/span&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 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; Flux 패턴&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의&lt;span&gt; MVC &lt;/span&gt;아키텍처는&lt;span&gt; &lt;/span&gt;컴포넌트의&lt;span&gt; &lt;/span&gt;재사용과&lt;span&gt; &lt;/span&gt;독립성에&lt;span&gt; &lt;/span&gt;중점을&lt;span&gt; &lt;/span&gt;둔&lt;span&gt; &lt;/span&gt;구조였습니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;그러나&lt;span&gt; &lt;/span&gt;프로젝트의&lt;span&gt; &lt;/span&gt;규모가&lt;span&gt; &lt;/span&gt;커지고&lt;span&gt; &lt;/span&gt;복잡성이&lt;span&gt; &lt;/span&gt;증가함에&lt;span&gt; &lt;/span&gt;따라&lt;span&gt;, &lt;b&gt;MVC&lt;/b&gt;&lt;/span&gt;&lt;b&gt;에서는&lt;span&gt; &lt;/span&gt;모델의&lt;span&gt; &lt;/span&gt;관리가&lt;span&gt; &lt;/span&gt;어려워지고&lt;span&gt; &lt;/span&gt;데이터의&lt;span&gt; &lt;/span&gt;흐름이&lt;span&gt; &lt;/span&gt;복잡해지는&lt;span&gt; &lt;/span&gt;문제가&lt;span&gt; &lt;/span&gt;발생&lt;/b&gt;했습니다&lt;span&gt;. &lt;/span&gt;특히&lt;span&gt;, &lt;/span&gt;같은&lt;span&gt; &lt;/span&gt;데이터를&lt;span&gt; &lt;/span&gt;공유할&lt;span&gt; &lt;/span&gt;때에는&lt;b&gt;&lt;span&gt; props&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;통해서만&lt;span&gt; &lt;/span&gt;데이터를&lt;span&gt; &lt;/span&gt;전달할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있어서&lt;span&gt; &lt;/span&gt;모델의&lt;span&gt; &lt;/span&gt;관리가&lt;span&gt; &lt;/span&gt;파편화되는&lt;span&gt; &lt;/span&gt;경향&lt;/b&gt;이&lt;span&gt; &lt;/span&gt;있었습니다&lt;span&gt;. &lt;/span&gt;이러한&lt;span&gt; &lt;/span&gt;문제에&lt;span&gt; &lt;/span&gt;대한&lt;span&gt; &lt;/span&gt;해결책으로&lt;span&gt; Flux &lt;/span&gt;패턴이&lt;span&gt; &lt;/span&gt;등장하게&lt;span&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 data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Flux&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;&lt;b&gt;단방향&lt;span&gt; &lt;/span&gt;데이터&lt;span&gt; &lt;/span&gt;흐름을&lt;span&gt; &lt;/span&gt;중심으로&lt;span&gt; &lt;/span&gt;한&lt;span&gt; &lt;/span&gt;아키텍처로&lt;span&gt;, &lt;/span&gt;데이터의&lt;span&gt; &lt;/span&gt;흐름을&lt;span&gt; &lt;/span&gt;명확히하여&lt;span&gt; &lt;/span&gt;애플리케이션의&lt;span&gt; &lt;/span&gt;상태&lt;span&gt; &lt;/span&gt;관리를&lt;span&gt; &lt;/span&gt;더욱&lt;span&gt; &lt;/span&gt;효율적으로&lt;span&gt; &lt;/span&gt;할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있게&lt;span&gt; &lt;/span&gt;해주었습니다&lt;span&gt;.&lt;/span&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;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;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;604&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Lscta/btsFW7ShNcB/wtMJul9x9BEqkyKvxYJink/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Lscta/btsFW7ShNcB/wtMJul9x9BEqkyKvxYJink/img.png&quot; data-alt=&quot;props drilling&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Lscta/btsFW7ShNcB/wtMJul9x9BEqkyKvxYJink/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLscta%2FbtsFW7ShNcB%2FwtMJul9x9BEqkyKvxYJink%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;1280&quot; height=&quot;604&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;604&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;props drilling&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1045&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2HAWz/btsFXIY1tmf/vB6yInUbd3Y335woxUQ6cK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2HAWz/btsFXIY1tmf/vB6yInUbd3Y335woxUQ6cK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2HAWz/btsFXIY1tmf/vB6yInUbd3Y335woxUQ6cK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2HAWz%2FbtsFXIY1tmf%2FvB6yInUbd3Y335woxUQ6cK%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;1280&quot; height=&quot;1045&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;1045&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;컴포넌트 구조가 복잡할 때에 발생하는 Props Drilling Problem&lt;/li&gt;
&lt;li&gt;특정 sibling에서 같은 데이터를 공유하고 사용하려 할 때 구조가 번거로워질 수밖에 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rArr; 단방향 아키텍처(uni-directional architecture)에 대한 제안이 등장한다.&lt;br /&gt;&amp;rArr; 비지니스 로직과 View를 아예 분리하며, 이 개념을 상태 관리(State Management)라고 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;MVC &lt;/span&gt;컴포넌트&lt;span&gt; &lt;/span&gt;관점에서&lt;span&gt; &lt;/span&gt;벗어나&lt;span&gt;, View&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;그냥&lt;span&gt; &lt;/span&gt;하나의&lt;span&gt; &lt;/span&gt;큰&lt;span&gt; &lt;/span&gt;단위로&lt;span&gt; &lt;/span&gt;바라보는&lt;span&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 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;1067&quot; data-origin-height=&quot;460&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ep7fI/btsFUCMLaQI/Yw7MqugqFW3BkQDR4sFIk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ep7fI/btsFUCMLaQI/Yw7MqugqFW3BkQDR4sFIk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ep7fI/btsFUCMLaQI/Yw7MqugqFW3BkQDR4sFIk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEp7fI%2FbtsFUCMLaQI%2FYw7MqugqFW3BkQDR4sFIk1%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;1067&quot; height=&quot;460&quot; data-origin-width=&quot;1067&quot; data-origin-height=&quot;460&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;p data-ke-size=&quot;size16&quot;&gt;View에서 Dispatch를 통해 Action을 전달 &amp;rarr; 전달된 Action에서는 Reducer를 통해 Store에 데이터를 보관 &amp;rarr; Store에 있는 데이터는 다시 View로 연결 (단방향 cycle)&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;Action&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Dispatcher&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Store&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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/SAskR/btsFWJEbVud/A4oId28IK6zkBuf2uGtYOK/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SAskR/btsFWJEbVud/A4oId28IK6zkBuf2uGtYOK/img.gif&quot; data-origin-width=&quot;550&quot; data-origin-height=&quot;475&quot; data-is-animation=&quot;true&quot; style=&quot;width: 43.4884%; margin-right: 10px;&quot; data-widthpercent=&quot;44&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SAskR/btsFWJEbVud/A4oId28IK6zkBuf2uGtYOK/img.gif&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSAskR%2FbtsFWJEbVud%2FA4oId28IK6zkBuf2uGtYOK%2Fimg.gif&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;475&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9tsNz/btsFUFCF8Hk/7gwfkIiA85XgILyTmE7DQ1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9tsNz/btsFUFCF8Hk/7gwfkIiA85XgILyTmE7DQ1/img.gif&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;475&quot; data-is-animation=&quot;true&quot; style=&quot;width: 55.3488%;&quot; data-widthpercent=&quot;56&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9tsNz/btsFUFCF8Hk/7gwfkIiA85XgILyTmE7DQ1/img.gif&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9tsNz%2FbtsFUFCF8Hk%2F7gwfkIiA85XgILyTmE7DQ1%2Fimg.gif&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;700&quot; height=&quot;475&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;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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Props drilling problem의 해소&lt;/li&gt;
&lt;li&gt;다양한 상태 관리 라이브러리가 등장하는 등 많은 영감을 줌 (Redux, Vuex 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&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;/li&gt;
&lt;li&gt;Action, Dispatch, Reducer&lt;span&gt;를&lt;/span&gt; &lt;span&gt;만들고&lt;/span&gt; &lt;span&gt;관리해야&lt;/span&gt; &lt;span&gt;하므로&lt;/span&gt; &lt;span&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;&amp;nbsp;&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;span&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;b&gt;Atomic Pattern&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거대한 View 영역과 Store 영역을 나누는 것은 동일하나, Action-Dispatch-Reducer 구조는 너무 복잡하기 때문에 손쉽게 Model에 접근하는 방법만 제공하는 것을 목표로 하는 패턴이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단한 문법으로 컴포넌트 외부에서 공통의 데이터를 set, get하고 동시에 동기화를 하는 방향성이다. 더불어 computed, derived, select 등의 반응형 기능을 제공하여 관련된 데이터의 동시 업데이트를 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Recoil, Svelte Store, Vue Composition, iotai 등이 해당한다.&lt;/p&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;React-Query&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상태 관리에 편향되어 있던 시각에서 벗어나 다시 MVC의 개념을 확대하는 방향으로, 고전적인 ajax의 데이터를 Model로 간주한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대부분의 프론트엔드 개발은 서버 데이터를 CRUD하고 UI를 그리는 것이 중점인데, Flux, Atomic은 비동기 데이터를 처리하기에는 너무 복잡한 방법이라는 관점이다.&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;Model&lt;/b&gt;: 서버에서 데이터를 fetch 해오는 영역&lt;/li&gt;
&lt;li&gt;&lt;b&gt;View&lt;/b&gt;: React&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Controller&lt;/b&gt;: query &amp;amp; mutation. 서버 데이터의 상태를 관리하고 캐싱, 동기화, refetch 등을 관리&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;GraphQL&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미리 스키마를 정의하고 이를 기반으로 데이터를 교환한다. (Schema based 아키텍처)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이&lt;span&gt; &lt;/span&gt;역시&lt;span&gt; &lt;/span&gt;서버&lt;span&gt; &lt;/span&gt;데이터를&lt;span&gt; Model&lt;/span&gt;로&lt;span&gt; &lt;/span&gt;간주하고&lt;span&gt;, &lt;/span&gt;서버와의&lt;span&gt; &lt;/span&gt;통신을&lt;span&gt; &lt;/span&gt;통해&lt;span&gt; View&lt;/span&gt;에게&lt;span&gt; &lt;/span&gt;데이터를&lt;span&gt; &lt;/span&gt;전달하는&lt;span&gt; &lt;/span&gt;방식이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/211</guid>
      <comments>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C%EC%99%80-%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4#entry211comment</comments>
      <pubDate>Wed, 20 Mar 2024 23:02:19 +0900</pubDate>
    </item>
    <item>
      <title>polling, websocket, sse 서버의 event를 클라이언트로 보내는 방법</title>
      <link>https://hmk1022.tistory.com/entry/polling-websocket-sse-%EC%84%9C%EB%B2%84%EC%9D%98-event%EB%A5%BC-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8%EB%A1%9C-%EB%B3%B4%EB%82%B4%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;664&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TSFIS/btsFQ0eGvb6/N1J03gKKwBB25LVDyCy7Rk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TSFIS/btsFQ0eGvb6/N1J03gKKwBB25LVDyCy7Rk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TSFIS/btsFQ0eGvb6/N1J03gKKwBB25LVDyCy7Rk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTSFIS%2FbtsFQ0eGvb6%2FN1J03gKKwBB25LVDyCy7Rk%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;1030&quot; height=&quot;664&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;664&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 id=&quot;polling&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;br /&gt;polling&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: #ee2323;&quot;&gt;&lt;b&gt;&lt;span&gt;클라이언트가 평범한 http request를 서버로 계속 날려서 이벤트 내용을 전달&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;받는 방식이다. &lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;가장 쉬운방법이지만 클라이언트가 계속적으로 request를 날리기때문에 클라이언가 많아지면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;서버의 부담이 급증&lt;/span&gt;&lt;/b&gt;&lt;span&gt;하게 된다. http request connection을 맺고 끊는것 자체가 부담이 많은 방식이다. 그리고 클라이언트에서 실시간정도의&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;빠른 응답을 기대하기도 어렵다.&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li id=&quot;SE-5dea742b-8428-4454-9ae1-4ffd75f077df&quot;&gt;polling은 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;http 오버헤드&lt;/span&gt;&lt;/b&gt;가 발생한다는 단점이 있다.&lt;/li&gt;
&lt;li id=&quot;SE-788bf065-5cbc-4612-950c-8dba8a02531c&quot;&gt;하지만 일정하게 갱신되는 서버 데이터의 경우 유용하게 사용할 수 있는 방식이다. (ex. 대시보드 갱신)&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SocketSSE(Server-Sent-Event)&lt;/p&gt;
&lt;table style=&quot;background-color: white; color: black; text-align: start; border-collapse: collapse; width: 100%; height: 236px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;Socket&lt;/td&gt;
&lt;td style=&quot;height: 18px;&quot;&gt;SSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;브라우저 지원&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;대부분 브라우저에서 지원&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;대부분 모던 브라우저 지원(polyfills 가능)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;통신 방향&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;양방향&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;일방향(서버에서 클라이언트로)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;리얼타임&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;Yes&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;데이터 형태&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;Binary, UTF-8&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;UTF-8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;자동 재접속&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;No&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;Yes(3초마다 제시도)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;height: 40px;&quot;&gt;최대 동시 접속 수&lt;/td&gt;
&lt;td style=&quot;height: 40px;&quot;&gt;브라우저 연결 한도는 없지만 서버 셋업에 따라 다름&lt;/td&gt;
&lt;td style=&quot;height: 40px;&quot;&gt;HTTP를 통해서 할 때는 브라우저당 6개 까지 가능 / HTTP2로는 100개가 기본&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;프로토콜&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;websocket&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;HTTP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;베터리 소모량&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;큼&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;작음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;Firewall 친화적&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;Nope&lt;/td&gt;
&lt;td style=&quot;height: 20px;&quot;&gt;Yes&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;h3 id=&quot;websocket&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;websocket&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 id=&quot;SE-2e074bff-a138-4704-9768-414102ae4b48&quot;&gt;양방향 채널을 이용해 채팅방 처럼 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;양방향 통신&lt;/b&gt;&lt;/span&gt;이 가능하다.&lt;/li&gt;
&lt;li&gt;기존 http요청 응답 방식은 요청한 그 클라이언트에만 응답이 가능했는데, ws 프로토콜을 통해 웹소켓 포트에 접속해 있는 모든 클라이언트에게 이벤트 방식으로 응답한다&lt;/li&gt;
&lt;li&gt;최초 접속이 일반&amp;nbsp;http request를 통해 handshaking과정을 통해 이루어 지기 떄문에, 기존의 80, 443 포트로 접속을 하므로 추가로 방화벽을 열지 않고도 양방향 통신이 가능하고, http 규격인 CORS적용이나 인증등의 과정을 기존과 동일하게 가저갈 수 있는것이 장점이다.&lt;/li&gt;
&lt;li id=&quot;SE-9e5470ed-f695-4a94-8eaa-e3576ab91a9f&quot;&gt;단, websocket 프로토콜을 처리하기 위해 전이중 연결과 새로운 웹소켓 서버가 필요하다.&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 id=&quot;sse_server-sent_events&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;SSE (Server-Sent Events)&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 id=&quot;SE-11c5071f-7031-4c03-b4dc-4b5728a9eb11&quot;&gt;HTML5 표준안이며 어느정도 웹소켓의 역할을 하면서 더 가볍다.&lt;/li&gt;
&lt;li id=&quot;SE-7058ae99-c164-4062-81cd-af558e9ff7e7&quot;&gt;websocket 과 같이 양방향이 아닌 &lt;u&gt;&lt;b&gt;server -&amp;gt; client 단방향&lt;/b&gt;&lt;/u&gt;이기에 서버의 event 나 message를 client 로 push 하는 작업에 유용하게 사용될 수 있다.&lt;/li&gt;
&lt;li id=&quot;SE-03e8954e-961a-43f8-b4dc-1c72a841fbc0&quot;&gt;양방향이 아니기에 요청 시 ajax로 쉽게 이용할 수 있다.&lt;/li&gt;
&lt;li id=&quot;SE-f2c857d4-a98f-4576-9c43-376ad6b94784&quot;&gt;재접속 처리 같은 대부분의 저수준 처리가 자동으로 지원된다.&lt;/li&gt;
&lt;li id=&quot;SE-93ce2d1a-77f7-4063-a98e-a61461532d87&quot;&gt;IE는 기본 미지원이지만, polyfill을 이용할 경우 IE를 포함한 크로스브라우징이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/210</guid>
      <comments>https://hmk1022.tistory.com/entry/polling-websocket-sse-%EC%84%9C%EB%B2%84%EC%9D%98-event%EB%A5%BC-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8%EB%A1%9C-%EB%B3%B4%EB%82%B4%EB%8A%94-%EB%B0%A9%EB%B2%95#entry210comment</comments>
      <pubDate>Sun, 17 Mar 2024 22:17:24 +0900</pubDate>
    </item>
    <item>
      <title>교착 상태 해결 방법</title>
      <link>https://hmk1022.tistory.com/entry/%EA%B5%90%EC%B0%A9-%EC%83%81%ED%83%9C-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;교착 상태 해결&lt;/h3&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;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;- 검출 후 회복&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;351&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BtyqT/btsFPcmSomk/fiGtkauS5mewxf1QW9iXkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BtyqT/btsFPcmSomk/fiGtkauS5mewxf1QW9iXkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BtyqT/btsFPcmSomk/fiGtkauS5mewxf1QW9iXkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBtyqT%2FbtsFPcmSomk%2FfiGtkauS5mewxf1QW9iXkk%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;833&quot; height=&quot;351&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;351&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;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;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;i&gt;상호배제 없애기&lt;/i&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 이론적으로 가능하지만 현실적인 해결법은 아니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;489&quot; data-origin-height=&quot;240&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y2QYN/btsFQy3vHJB/BjzKUhBIGwckFiW4e8YsMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y2QYN/btsFQy3vHJB/BjzKUhBIGwckFiW4e8YsMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y2QYN/btsFQy3vHJB/BjzKUhBIGwckFiW4e8YsMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy2QYN%2FbtsFQy3vHJB%2FBjzKUhBIGwckFiW4e8YsMK%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;489&quot; height=&quot;240&quot; data-origin-width=&quot;489&quot; data-origin-height=&quot;240&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;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;i&gt;점유와 대기 없애기&lt;/i&gt;(자원을 할당받은 상태에서 자원을 대기하는 것)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 프로세스에 자원을 모두 할당하거나, 아예 할당하지 않는 방식으로 배분&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&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;&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;i&gt; 비선점 조건을 없애기&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선점이 가능한 자원(e.g CPU)에 한해 효과적&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 모든 자원이 선점 가능한 것은 아니다. (한 프로세스의 작업이 끝날 때까지 다른 프로세스는 이용할 수 있는 자원이 꽤 있음. ex 프린터)&lt;/p&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;size18&quot;&gt;&lt;i&gt;원형 대기 조건 없애기(서로가 서로의 자원을 기다리는 방식)&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 자원에 번호를 붙이고 오름차순으로 할당하면 원형 대기는 발생하지 않음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 자원에 번호를 붙이는 것은 어려운 작업, 어떤 자원에 어떤 번호를 붙이느냐에 따라 활용률이 달라진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;=&amp;gt; 그나마 가장 실용적이고 현실적인 방법&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;405&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5kGbE/btsFQ0rXY7q/Z1BhJHUQb7oTcKomb7UwK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5kGbE/btsFQ0rXY7q/Z1BhJHUQb7oTcKomb7UwK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5kGbE/btsFQ0rXY7q/Z1BhJHUQb7oTcKomb7UwK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5kGbE%2FbtsFQ0rXY7q%2FZ1BhJHUQb7oTcKomb7UwK1%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;443&quot; height=&quot;405&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;405&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&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;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안전 순서열 : 교착 상태 없이 안전하게 프로세스들에 자원을&amp;nbsp;할당할 수 있는 순서&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;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;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;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;회피 예시&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 컴퓨터 시스템에 총 12개의 자원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 프로세스 P1, P2, P3가 각각 5개, 2개, 2개의 자원을 할당받아 실행 중 (운영체제가 배분할 수 있는 자원의 개수는? 3개)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 프로세스 P1, P2, P3는 각각 최대 10개, 4개, 9개 자원을 요구할 수 있다고 가정&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;497&quot; data-origin-height=&quot;185&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1nvou/btsFQtOJBBa/0oDEGhcxxR9bDFp6Q2gyHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1nvou/btsFQtOJBBa/0oDEGhcxxR9bDFp6Q2gyHK/img.png&quot; data-alt=&quot;안전 순서열이 존재:&amp;amp;nbsp;P1 -&amp;amp;gt; P2 -&amp;amp;gt; P3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1nvou/btsFQtOJBBa/0oDEGhcxxR9bDFp6Q2gyHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1nvou%2FbtsFQtOJBBa%2F0oDEGhcxxR9bDFp6Q2gyHK%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;185&quot; data-origin-width=&quot;497&quot; data-origin-height=&quot;185&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;안전 순서열이 존재:&amp;nbsp;P1 -&amp;gt; P2 -&amp;gt; P3&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;&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;size18&quot;&gt;프로세스 P1, P2, P3이 모두 최대로 자원을 요구한 최악의 상황 가정&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;888&quot; data-origin-height=&quot;468&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5FkV1/btsFRbGNcKT/fBRfzm6KQt1sdHYx1eMbJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5FkV1/btsFRbGNcKT/fBRfzm6KQt1sdHYx1eMbJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5FkV1/btsFRbGNcKT/fBRfzm6KQt1sdHYx1eMbJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5FkV1%2FbtsFRbGNcKT%2FfBRfzm6KQt1sdHYx1eMbJK%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;712&quot; height=&quot;375&quot; data-origin-width=&quot;888&quot; data-origin-height=&quot;468&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wPlxA/btsFQPxsoqv/q5fBtG2fEkBS96a4ikkXL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wPlxA/btsFQPxsoqv/q5fBtG2fEkBS96a4ikkXL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wPlxA/btsFQPxsoqv/q5fBtG2fEkBS96a4ikkXL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwPlxA%2FbtsFQPxsoqv%2Fq5fBtG2fEkBS96a4ikkXL1%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;692&quot; height=&quot;333&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;424&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1055&quot; data-origin-height=&quot;479&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZLu47/btsFP2YnRXj/qhRS2tTFXgCzkFloPsHQC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZLu47/btsFP2YnRXj/qhRS2tTFXgCzkFloPsHQC0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZLu47/btsFP2YnRXj/qhRS2tTFXgCzkFloPsHQC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZLu47%2FbtsFP2YnRXj%2FqhRS2tTFXgCzkFloPsHQC0%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;710&quot; height=&quot;322&quot; data-origin-width=&quot;1055&quot; data-origin-height=&quot;479&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;463&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ng6nO/btsFRk4QbUw/m5QtCw4uA1rlUToYUQ4QKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ng6nO/btsFRk4QbUw/m5QtCw4uA1rlUToYUQ4QKk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ng6nO/btsFRk4QbUw/m5QtCw4uA1rlUToYUQ4QKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNg6nO%2FbtsFRk4QbUw%2Fm5QtCw4uA1rlUToYUQ4QKk%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;652&quot; height=&quot;345&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;463&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1046&quot; data-origin-height=&quot;508&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GiBUv/btsFSam30ym/9jzKnGeSu65G4BkcsR42sk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GiBUv/btsFSam30ym/9jzKnGeSu65G4BkcsR42sk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GiBUv/btsFSam30ym/9jzKnGeSu65G4BkcsR42sk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGiBUv%2FbtsFSam30ym%2F9jzKnGeSu65G4BkcsR42sk%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;648&quot; height=&quot;315&quot; data-origin-width=&quot;1046&quot; data-origin-height=&quot;508&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;- c.f. 은행원 알고리즘&lt;/p&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;/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;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;&lt;/p&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;/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;size18&quot;&gt;&amp;nbsp;&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;/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;gt; 작업 내역을 잃을 위험)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 교착 상태가 해결될 때까지 한 프로세스씩 강제 종료(-&amp;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;b&gt;Reference&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;&lt;a href=&quot;https://www.youtube.com/watch?v=zQDNXklvdUw&amp;amp;list=PLVsNizTWUw7FCS83JhC1vflK8OcLRG0Hl&amp;amp;index=38&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=zQDNXklvdUw&amp;amp;list=PLVsNizTWUw7FCS83JhC1vflK8OcLRG0Hl&amp;amp;index=38&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>OS</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/209</guid>
      <comments>https://hmk1022.tistory.com/entry/%EA%B5%90%EC%B0%A9-%EC%83%81%ED%83%9C-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95#entry209comment</comments>
      <pubDate>Sat, 16 Mar 2024 21:10:10 +0900</pubDate>
    </item>
    <item>
      <title>교착상태(Dead lock)</title>
      <link>https://hmk1022.tistory.com/entry/%EA%B5%90%EC%B0%A9%EC%83%81%ED%83%9CDead-lock</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;i&gt;두 개 이상의 프로세스가 각자 갖고 있는 자원들을 그저 기다리기만 한다면,&lt;/i&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;식사하는 철학자 문제로 엿보는 교착상태&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;음식을 먹으려면 꼭 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;&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;937&quot; data-origin-height=&quot;365&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mPRSq/btsFO1w5ah6/TFoV6UhQ3MP8EO64hW5PI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mPRSq/btsFO1w5ah6/TFoV6UhQ3MP8EO64hW5PI1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mPRSq/btsFO1w5ah6/TFoV6UhQ3MP8EO64hW5PI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmPRSq%2FbtsFO1w5ah6%2FTFoV6UhQ3MP8EO64hW5PI1%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;937&quot; height=&quot;365&quot; data-origin-width=&quot;937&quot; data-origin-height=&quot;365&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 style=&quot;color: #333333; text-align: start;&quot; 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;이런 식으로 일어나지 않을 사건을 기다리며 진행이 멈춰 버리는 현상을 &quot;교착상태&quot;라고 합니다.&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;498&quot; data-origin-height=&quot;451&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c3V20Q/btsFOcMNSQk/Qp0VWtCuZq3OpqRUck3hJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c3V20Q/btsFOcMNSQk/Qp0VWtCuZq3OpqRUck3hJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c3V20Q/btsFOcMNSQk/Qp0VWtCuZq3OpqRUck3hJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc3V20Q%2FbtsFOcMNSQk%2FQp0VWtCuZq3OpqRUck3hJ1%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;498&quot; height=&quot;451&quot; data-origin-width=&quot;498&quot; data-origin-height=&quot;451&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 철학자는 프로세스고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포크는 실행에 꼭 필요한 자원&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;식사는 자원을 이용함 =&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;서로가 점거하고 있는 자원을 서로가 기다리면 그 어떤 스레드나 프로세스가 실행될 수 없음을 시사합니다.&lt;/p&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;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;&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bRwEir/btsFNutopHc/OLlEQQvJlGFgoEIchlZGo0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bRwEir/btsFNutopHc/OLlEQQvJlGFgoEIchlZGo0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bRwEir/btsFNutopHc/OLlEQQvJlGFgoEIchlZGo0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbRwEir%2FbtsFNutopHc%2FOLlEQQvJlGFgoEIchlZGo0%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;810&quot; height=&quot;366&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;366&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;h3 data-ke-size=&quot;size23&quot;&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;/h4&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;/p&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;1. 프로세스는 원으로, 자원(cpu, 메모리 등등)의 종류는 사각형으로 표현&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;775&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BBUPG/btsFLVMgKBb/oN5u5j5gRrqTVZmPn0Fla1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BBUPG/btsFLVMgKBb/oN5u5j5gRrqTVZmPn0Fla1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BBUPG/btsFLVMgKBb/oN5u5j5gRrqTVZmPn0Fla1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBBUPG%2FbtsFLVMgKBb%2FoN5u5j5gRrqTVZmPn0Fla1%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;775&quot; height=&quot;400&quot; data-origin-width=&quot;775&quot; data-origin-height=&quot;400&quot;/&gt;&lt;/span&gt;&lt;/figure&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-origin-width=&quot;823&quot; data-origin-height=&quot;380&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNwpAi/btsFLRDgi72/TB1C47d0b86BRpMqJmhQ00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNwpAi/btsFLRDgi72/TB1C47d0b86BRpMqJmhQ00/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNwpAi/btsFLRDgi72/TB1C47d0b86BRpMqJmhQ00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNwpAi%2FbtsFLRDgi72%2FTB1C47d0b86BRpMqJmhQ00%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;823&quot; height=&quot;380&quot; data-origin-width=&quot;823&quot; data-origin-height=&quot;380&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;597&quot; data-origin-height=&quot;429&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WFVrY/btsFPrh0ux6/KkrvPkeF1kixd1buQ4mSn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WFVrY/btsFPrh0ux6/KkrvPkeF1kixd1buQ4mSn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WFVrY/btsFPrh0ux6/KkrvPkeF1kixd1buQ4mSn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWFVrY%2FbtsFPrh0ux6%2FKkrvPkeF1kixd1buQ4mSn0%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;597&quot; height=&quot;429&quot; data-origin-width=&quot;597&quot; data-origin-height=&quot;429&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;4. 프로세스가 어떤 자월을 기다리고 있다면 프로세스에서 자원으로 화살표를 표시&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;371&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qmhdc/btsFLO0OtKB/KkK3yUzIyOoJSdsUzFMrA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qmhdc/btsFLO0OtKB/KkK3yUzIyOoJSdsUzFMrA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qmhdc/btsFLO0OtKB/KkK3yUzIyOoJSdsUzFMrA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqmhdc%2FbtsFLO0OtKB%2FKkK3yUzIyOoJSdsUzFMrA1%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;371&quot; data-origin-width=&quot;660&quot; data-origin-height=&quot;371&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;SSD는 3개 CPU가 3개 프린터가 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;p data-ke-size=&quot;size16&quot;&gt;A - SSD&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;B - CPU&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C - CPU&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;D - 프린터&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;E - 프린터의 사용 기다림&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;F - CPU 할당을 기다림&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;410&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dr78eF/btsFOmPdNnD/2mTYECNriXrc7jp3aPNtk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dr78eF/btsFOmPdNnD/2mTYECNriXrc7jp3aPNtk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dr78eF/btsFOmPdNnD/2mTYECNriXrc7jp3aPNtk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdr78eF%2FbtsFOmPdNnD%2F2mTYECNriXrc7jp3aPNtk1%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;810&quot; height=&quot;410&quot; data-origin-width=&quot;810&quot; data-origin-height=&quot;410&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;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-origin-width=&quot;896&quot; data-origin-height=&quot;374&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmIDUa/btsFMNmE8gO/iftP1Eg10f2I0kKfy8wqXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmIDUa/btsFMNmE8gO/iftP1Eg10f2I0kKfy8wqXk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmIDUa/btsFMNmE8gO/iftP1Eg10f2I0kKfy8wqXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmIDUa%2FbtsFMNmE8gO%2FiftP1Eg10f2I0kKfy8wqXk%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;896&quot; height=&quot;374&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;374&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;교착 상태가 일어나는 근본적인 이유 이해하기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&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;2. 점유와 대기 - 자원을 할당 받은 상태에서 다른 자원을 기다리고 있는 상태 (위의 예시 중 게임과 브라우저 그림 &amp;amp; 철학자 식사 그림 참고)&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;&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;&amp;nbsp;&lt;/p&gt;</description>
      <category>OS</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/208</guid>
      <comments>https://hmk1022.tistory.com/entry/%EA%B5%90%EC%B0%A9%EC%83%81%ED%83%9CDead-lock#entry208comment</comments>
      <pubDate>Fri, 15 Mar 2024 00:03:42 +0900</pubDate>
    </item>
    <item>
      <title>자바스크립트의 call by value와 call by reference</title>
      <link>https://hmk1022.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%9D%98-call-by-value%EC%99%80-call-by-reference</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트에서&lt;span&gt; &lt;/span&gt;함수&lt;span&gt; &lt;/span&gt;호출&lt;span&gt; &lt;/span&gt;방식인&lt;span&gt; Call by Value&lt;/span&gt;와&lt;span&gt; Call by Reference&lt;/span&gt;에&lt;span&gt; &lt;/span&gt;대해&lt;span&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;/span&gt;개념을&lt;span&gt; &lt;/span&gt;살펴보고&lt;span&gt;, &lt;/span&gt;이것이&lt;span&gt; &lt;/span&gt;리액트에서&lt;span&gt; &lt;/span&gt;상태값을&lt;span&gt; &lt;/span&gt;업데이트&lt;span&gt; &lt;/span&gt;할&lt;span&gt; &lt;/span&gt;때&lt;span&gt; &lt;/span&gt;어떻게&lt;span&gt; &lt;/span&gt;작용할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있는지&lt;span&gt; &lt;/span&gt;살펴볼&lt;span&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;&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;532&quot; data-origin-height=&quot;383&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dzspXJ/btsFJ43t65L/X4I9PaJO91LtkJvyg83HE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dzspXJ/btsFJ43t65L/X4I9PaJO91LtkJvyg83HE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dzspXJ/btsFJ43t65L/X4I9PaJO91LtkJvyg83HE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdzspXJ%2FbtsFJ43t65L%2FX4I9PaJO91LtkJvyg83HE1%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;532&quot; height=&quot;383&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;383&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;p data-ke-size=&quot;size16&quot;&gt;자바스크립트에서&lt;span&gt; &lt;/span&gt;함수를&lt;span&gt; &lt;/span&gt;호출할때&lt;span&gt; &lt;/span&gt;매개변수를&lt;span&gt; &lt;/span&gt;할당&lt;span&gt; &lt;/span&gt;받을&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;매개변수는&lt;span&gt; &lt;/span&gt;여러개가&lt;span&gt; &lt;/span&gt;될수도있고&lt;span&gt; &lt;/span&gt;단일값일수도있고&lt;span&gt; &lt;/span&gt;객체나&lt;span&gt; &lt;/span&gt;또&lt;span&gt; &lt;/span&gt;다른&lt;span&gt; &lt;/span&gt;함수가&lt;span&gt; &lt;/span&gt;될&lt;span&gt; &lt;/span&gt;수도&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;. &lt;br /&gt;&lt;/span&gt;&lt;b&gt;매개변수를&lt;span&gt; &lt;/span&gt;전달하는&lt;span&gt; &lt;/span&gt;방식에&lt;span&gt; &lt;/span&gt;따라서&lt;/b&gt;&lt;span&gt; Call by value , Call by reference &lt;/span&gt;로&lt;span&gt; &lt;/span&gt;나눌&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;br /&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;Call by Value (값에 의한 호출)&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;span&gt;Call by Value&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;함수에&lt;span&gt; &lt;/span&gt;인자를&lt;span&gt; &lt;/span&gt;전달할&lt;span&gt; &lt;/span&gt;때&lt;span&gt;, &lt;/span&gt;해당&lt;span&gt; &lt;/span&gt;값의&lt;span&gt; &lt;/span&gt;복사본이&lt;span&gt; &lt;/span&gt;함수로&lt;span&gt; &lt;/span&gt;전달되는&lt;span&gt; &lt;/span&gt;방식을&lt;span&gt; &lt;/span&gt;말합니다&lt;span&gt;. &lt;/span&gt;이는&lt;span&gt; &lt;/span&gt;&lt;b&gt;원시&lt;span&gt; &lt;/span&gt;데이터&lt;span&gt; &lt;/span&gt;타입&lt;span&gt;(&lt;/span&gt;숫자&lt;span&gt;, &lt;/span&gt;문자열&lt;span&gt;, &lt;/span&gt;불리언&lt;span&gt; &lt;/span&gt;등&lt;span&gt;)&lt;/span&gt;을&lt;span&gt; &lt;/span&gt;다룰&lt;span&gt; &lt;/span&gt;때&lt;span&gt; &lt;/span&gt;발생&lt;/b&gt;합니다&lt;span&gt;. &lt;/span&gt;함수&lt;span&gt; &lt;/span&gt;안에서&lt;span&gt; &lt;/span&gt;매개변수&lt;span&gt; &lt;/span&gt;값을&lt;span&gt; &lt;/span&gt;변경하더라도&lt;span&gt; &lt;/span&gt;호출한&lt;span&gt; &lt;/span&gt;곳의&lt;span&gt; &lt;/span&gt;변수&lt;span&gt; &lt;/span&gt;값에는&lt;span&gt; &lt;/span&gt;영향이&lt;span&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 data-ke-size=&quot;size16&quot;&gt;단일 값에 의한 매배변수 전달은 함수를 호출했을때 함수내에서 지역변수로서 사용되며 따라서 값이 복사되어 사용됩니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;즉,&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;함수&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;내에서만&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;값의&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;변경이&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;발생하고&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;원본&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;값에는&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;영향을&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;주지&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;않습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 값의&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;불변성을&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;유지할&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;수&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;있지만&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- 지역변수로&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;복사하여&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;활용하는만큼&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;메모리를&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&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;pre id=&quot;code_1710330465006&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function increment(x) {
  x++;
}

let num = 5;
increment(num);
console.log(num); // 출력 결과: 5&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;Call by Reference (참조에 의한 호출)&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;span&gt;Call by Reference&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;함수에&lt;span&gt; &lt;/span&gt;인자로&lt;span&gt; &lt;/span&gt;변수의&lt;span&gt; &lt;/span&gt;주소&lt;span&gt;(&lt;/span&gt;참조&lt;span&gt;)&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;전달되는&lt;span&gt; &lt;/span&gt;방식을&lt;span&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;b&gt;객체나&lt;span&gt; &lt;/span&gt;배열과&lt;span&gt; &lt;/span&gt;같은&lt;span&gt; &lt;/span&gt;참조형&lt;span&gt; &lt;/span&gt;데이터&lt;span&gt; &lt;/span&gt;타입을&lt;span&gt; &lt;/span&gt;다룰&lt;span&gt; &lt;/span&gt;때&lt;span&gt; &lt;/span&gt;발생&lt;/b&gt;합니다&lt;span&gt;. &lt;/span&gt;함수&lt;span&gt; &lt;/span&gt;내에서&lt;span&gt; &lt;/span&gt;객체의&lt;span&gt; &lt;/span&gt;속성을&lt;span&gt; &lt;/span&gt;변경하면&lt;span&gt;, &lt;/span&gt;호출한&lt;span&gt; &lt;/span&gt;곳의&lt;span&gt; &lt;/span&gt;객체에도&lt;span&gt; &lt;/span&gt;영향을&lt;span&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 data-ke-size=&quot;size16&quot;&gt;객체 즉, 참조에 의한 매개변수 전달은 값이 전달되는것이 아니라 &lt;b&gt;해당 객체가 저장된 메모리의 주소를 넘겨주게됩니다&lt;/b&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 값의 복사가 아니라 원본데이터와 동일한 메모리주소를 바라보고 있습니다.&lt;/p&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;span&gt; &lt;/span&gt;복사가&lt;span&gt; &lt;/span&gt;아닌&lt;span&gt; &lt;/span&gt;메모리에&lt;span&gt; &lt;/span&gt;직접&lt;span&gt; &lt;/span&gt;접근이기&lt;span&gt; &lt;/span&gt;때문에&lt;span&gt; &lt;/span&gt;처리가&lt;span&gt; &lt;/span&gt;빠르고&lt;span&gt; &lt;/span&gt;메모리를&lt;span&gt; &lt;/span&gt;절약&lt;span&gt; &lt;/span&gt;할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있지만&lt;span&gt; &lt;/span&gt;&lt;b&gt;원본데이터의&lt;span&gt; &lt;/span&gt;불변성이&lt;span&gt; &lt;/span&gt;지켜지지&lt;span&gt; &lt;/span&gt;않는다는&lt;span&gt; &lt;/span&gt;단점&lt;/b&gt;이&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1710330531126&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function addElement(arr, element) {
  arr.push(element);
}

let myArray = [1, 2, 3];
addElement(myArray, 4);
console.log(myArray); // 출력 결과: [1, 2, 3, 4]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;React의 useState와 Call by reference&lt;/h4&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; &lt;/span&gt;상태값이&lt;span&gt; &lt;/span&gt;업데이트되지&lt;span&gt; &lt;/span&gt;않는&lt;span&gt; &lt;/span&gt;문제는&lt;span&gt; &lt;/span&gt;주로&lt;span&gt; &lt;/span&gt;객체나&lt;span&gt; &lt;/span&gt;배열과&lt;span&gt; &lt;/span&gt;같은&lt;span&gt; &lt;/span&gt;참조형&lt;span&gt; &lt;/span&gt;데이터를&lt;span&gt; &lt;/span&gt;다룰&lt;span&gt; &lt;/span&gt;때&lt;span&gt; &lt;/span&gt;발생할&lt;span&gt; &lt;/span&gt;수&lt;span&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; JavaScript&lt;/span&gt;의&lt;span&gt; &lt;/span&gt;특성&lt;span&gt; &lt;/span&gt;중&lt;span&gt; Call by Reference&lt;/span&gt;와&lt;span&gt; &lt;/span&gt;관련이&lt;span&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;/span&gt;이해하고&lt;span&gt; &lt;/span&gt;해결하기&lt;span&gt; &lt;/span&gt;위해서는&lt;span&gt; &lt;/span&gt;상태값을&lt;span&gt; &lt;/span&gt;업데이트할&lt;span&gt; &lt;/span&gt;때&lt;span&gt; &lt;/span&gt;주의해야&lt;span&gt; &lt;/span&gt;할&lt;span&gt; &lt;/span&gt;몇&lt;span&gt; &lt;/span&gt;가지&lt;span&gt; &lt;/span&gt;사항이&lt;span&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 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. 불변성(Immutability) 유지:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리액트에서&lt;span&gt; &lt;/span&gt;상태를&lt;span&gt; &lt;/span&gt;업데이트할&lt;span&gt; &lt;/span&gt;때는&lt;span&gt; &lt;/span&gt;기존&lt;span&gt; &lt;/span&gt;상태를&lt;span&gt; &lt;/span&gt;직접&lt;span&gt; &lt;/span&gt;수정하지&lt;span&gt; &lt;/span&gt;말고&lt;span&gt;, &lt;/span&gt;이전&lt;span&gt; &lt;/span&gt;상태를&lt;span&gt; &lt;/span&gt;기반으로&lt;span&gt; &lt;/span&gt;새로운&lt;span&gt; &lt;/span&gt;객체나&lt;span&gt; &lt;/span&gt;배열을&lt;span&gt; &lt;/span&gt;생성하여&lt;span&gt; &lt;/span&gt;사용해야&lt;span&gt; &lt;/span&gt;합니다&lt;span&gt;. &lt;/span&gt;불변성을&lt;span&gt; &lt;/span&gt;유지하지&lt;span&gt; &lt;/span&gt;않으면&lt;span&gt; React&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;상태&lt;span&gt; &lt;/span&gt;변화를&lt;span&gt; &lt;/span&gt;감지하지&lt;span&gt; &lt;/span&gt;못하고&lt;span&gt; &lt;/span&gt;리렌더링이&lt;span&gt; &lt;/span&gt;이뤄지지&lt;span&gt; &lt;/span&gt;않을&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1710331083067&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 잘못된 방법
const incrementCount = () =&amp;gt; {
  setCount({ value: count.value + 1 });
};

// 올바른 방법: spread 연산자를 사용하여 새로운 객체 생성
const incrementCount = () =&amp;gt; {
  setCount(prevState =&amp;gt; {
    return { ...prevState, value: prevState.value + 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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 함수형 업데이트 사용:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;setState&lt;/span&gt;에서&lt;span&gt; &lt;/span&gt;제공하는&lt;span&gt; &lt;/span&gt;함수형&lt;span&gt; &lt;/span&gt;업데이트를&lt;span&gt; &lt;/span&gt;활용하면&lt;span&gt;, &lt;/span&gt;이전&lt;span&gt; &lt;/span&gt;상태를&lt;span&gt; &lt;/span&gt;바탕으로&lt;span&gt; &lt;/span&gt;업데이트를&lt;span&gt; &lt;/span&gt;수행할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;. &lt;/span&gt;이렇게&lt;span&gt; &lt;/span&gt;하면&lt;span&gt; &lt;/span&gt;현재&lt;span&gt; &lt;/span&gt;상태의&lt;span&gt; &lt;/span&gt;참조를&lt;span&gt; &lt;/span&gt;직접&lt;span&gt; &lt;/span&gt;변경하지&lt;span&gt; &lt;/span&gt;않아도&lt;span&gt; &lt;/span&gt;안전하게&lt;span&gt; &lt;/span&gt;상태를&lt;span&gt; &lt;/span&gt;업데이트할&lt;span&gt; &lt;/span&gt;수&lt;span&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;pre id=&quot;code_1710331103304&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const incrementCount = () =&amp;gt; {
  setCount(prevState =&amp;gt; ({ ...prevState, value: prevState.value + 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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 깊은 복사 활용:&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체나&lt;span&gt; &lt;/span&gt;배열을&lt;span&gt; &lt;/span&gt;다룰&lt;span&gt; &lt;/span&gt;때는&lt;span&gt; &lt;/span&gt;깊은&lt;span&gt; &lt;/span&gt;복사를&lt;span&gt; &lt;/span&gt;활용하여&lt;span&gt; &lt;/span&gt;복사본을&lt;span&gt; &lt;/span&gt;생성한&lt;span&gt; &lt;/span&gt;후&lt;span&gt; &lt;/span&gt;업데이트&lt;span&gt; &lt;/span&gt;작업을&lt;span&gt; &lt;/span&gt;수행할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있습니다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1710331122189&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const updateArray = () =&amp;gt; {
  const newArray = [...myArray];
  newArray.push(4);
  setMyArray(newArray);
};&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;&lt;b&gt;4. Object.assign &lt;/b&gt;&lt;span&gt;&lt;b&gt;사용&lt;/b&gt;&lt;/span&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;span&gt;Object.assign &lt;/span&gt;함수를&lt;span&gt; &lt;/span&gt;사용하여&lt;span&gt; &lt;/span&gt;객체를&lt;span&gt; &lt;/span&gt;복사하고&lt;span&gt; &lt;/span&gt;업데이트할&lt;span&gt; &lt;/span&gt;수도&lt;span&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;pre id=&quot;code_1710331152683&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const incrementCount = () =&amp;gt; {
  setCount(prevState =&amp;gt; Object.assign({}, prevState, { value: prevState.value + 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;p data-ke-size=&quot;size16&quot;&gt;상태값을&lt;span&gt; &lt;/span&gt;업데이트할&lt;span&gt; &lt;/span&gt;때&lt;span&gt; &lt;/span&gt;이러한&lt;span&gt; &lt;/span&gt;방식을&lt;span&gt; &lt;/span&gt;고려하면&lt;span&gt; &lt;/span&gt;리액트&lt;span&gt; &lt;/span&gt;애플리케이션에서&lt;span&gt; &lt;/span&gt;발생하는&lt;span&gt; &lt;/span&gt;상태&lt;span&gt; &lt;/span&gt;업데이트&lt;span&gt; &lt;/span&gt;문제를&lt;span&gt; &lt;/span&gt;해결할&lt;span&gt; &lt;/span&gt;수&lt;span&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;/span&gt;유지하고&lt;span&gt;, &lt;/span&gt;함수형&lt;span&gt; &lt;/span&gt;업데이트를&lt;span&gt; &lt;/span&gt;사용하며&lt;span&gt;, &lt;/span&gt;적절한&lt;span&gt; &lt;/span&gt;복사&lt;span&gt; &lt;/span&gt;방식을&lt;span&gt; &lt;/span&gt;선택하여&lt;span&gt; &lt;/span&gt;상태를&lt;span&gt; &lt;/span&gt;업데이트하는&lt;span&gt; &lt;/span&gt;습관을&lt;span&gt; 기르면 좋겠네요 :)&lt;/span&gt;&lt;/p&gt;</description>
      <category>javascript</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/207</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%9D%98-call-by-value%EC%99%80-call-by-reference#entry207comment</comments>
      <pubDate>Wed, 13 Mar 2024 21:00:17 +0900</pubDate>
    </item>
    <item>
      <title>자바스크립트 가비지 콜렉션</title>
      <link>https://hmk1022.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BD%9C%EB%A0%89%EC%85%98</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;가비지&amp;nbsp;콜렉션이란?&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;h4 data-ke-size=&quot;size20&quot;&gt;메모리&amp;nbsp;관리의&amp;nbsp;중요성&lt;/h4&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;해결하여&amp;nbsp;개발자가&amp;nbsp;메모리를&amp;nbsp;효율적으로&amp;nbsp;사용할&amp;nbsp;수&amp;nbsp;있도록&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;가비지&amp;nbsp;콜렉션의&amp;nbsp;작동&amp;nbsp;원리&lt;/h4&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;중에&amp;nbsp;동적으로&amp;nbsp;생성되는&amp;nbsp;객체들&amp;nbsp;중에서&amp;nbsp;필요&amp;nbsp;없어진&amp;nbsp;것들을&amp;nbsp;체크하는&amp;nbsp;방식으로&amp;nbsp;이루어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1.&amp;nbsp;레퍼런스&amp;nbsp;카운팅&amp;nbsp;방식&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&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;참조&amp;nbsp;카운트가&amp;nbsp;0이&amp;nbsp;되면&amp;nbsp;해당&amp;nbsp;객체를&amp;nbsp;해제하는&amp;nbsp;방식입니다.&amp;nbsp;이&amp;nbsp;방식은&amp;nbsp;&lt;b&gt;단순하고&amp;nbsp;빠르지만&amp;nbsp;순환&amp;nbsp;참조(circular&amp;nbsp;references)&amp;nbsp;문제에&amp;nbsp;취약&lt;/b&gt;합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1710078346207&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let x = {
  a: {
    b: 2,
  },
};
// 2개의 객체가 생성되었습니다. 하나의 객체는 다른 객체의 속성으로 참조됩니다.
// 나머지 하나는 'x' 변수에 할당되어 참조됩니다.
// 명백하게, 가비지 콜렉션 수행될 메모리는 하나도 없습니다.

let y = x;
// 'y' 변수는 위의 객체를 참조하는 두 번째 변수입니다.

x = 1;
// 이제 'y' 변수가 위의 객체를 참조하는 유일한 변수가 되었습니다.

let z = y.a;
// 위의 객체의 'a' 속성을 참조했습니다.
// 이제 이 객체는 두 개의 참조를 가집니다.
// 'y'가 속성으로 참조하고 'z'라는 변수가 참조합니다.

y = &quot;mozilla&quot;;
// 이제 맨 처음 'x' 변수가 참조했던 객체에 대한 참조가 없기 때문에, 가비지 컬렉션이 가능합니다.
// 그러나, 객체의 'a' 속성이 여전히 'z' 변수에 의해 참조되므로
// 메모리를 해제할 수 없습니다.

z = null;
// 이제 맨 처음 'x' 변수가 참조했던 객체의 'a' 속성에는
// 참조가 없으므로 가비지 콜렉션이 수행될 수 있습니다.&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;size18&quot;&gt;순환 참조한계&lt;/p&gt;
&lt;pre id=&quot;code_1710078398555&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function f() {
  const x = {};
  const y = {};
  x.a = y; // x는 y를 참조합니다.
  y.a = x; // y는 x를 참조합니다.

  return &quot;azerty&quot;;
}

f();&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;h4 data-ke-size=&quot;size20&quot;&gt;2.&amp;nbsp;마크&amp;nbsp;앤&amp;nbsp;스위프(Mark&amp;nbsp;and&amp;nbsp;Sweep)&amp;nbsp;방식&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: -webkit-left;&quot;&gt;&quot;sweep(쓸어버린다)&quot;라고 이름을 붙였듯이, 이건 힙 메모리에 있는 모든 도달 불가능한 객체를 치워버립니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&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;하나입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 거의 모든 최신 자바스크립트엔진은 해당 방식을 사용합니다. 이 알고리즘은 다음과 같은 단계로 작동합니다.&lt;br /&gt;&lt;br /&gt;마크(Mark)&amp;nbsp;단계:&amp;nbsp;루트(root)로부터&amp;nbsp;시작해&amp;nbsp;모든&amp;nbsp;도달&amp;nbsp;가능한(Reachable)&amp;nbsp;객체를&amp;nbsp;표시(mark)합니다.&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;않습니다.&lt;br /&gt;&lt;br /&gt;스위프(Sweep)&amp;nbsp;단계:&amp;nbsp;마크되지&amp;nbsp;않은&amp;nbsp;모든&amp;nbsp;객체를&amp;nbsp;해제(sweep)합니다.&amp;nbsp;이&amp;nbsp;단계에서는&amp;nbsp;가비지로&amp;nbsp;판단되는&amp;nbsp;객체들을&amp;nbsp;해제하고,&amp;nbsp;메모리를&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;size18&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. 모든 객체들의 marked bit들을 false로 설정&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;674&quot; data-origin-height=&quot;262&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zJSux/btsFF3o0Eol/vtXKobB4pzw5DLuU1z6O71/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zJSux/btsFF3o0Eol/vtXKobB4pzw5DLuU1z6O71/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zJSux/btsFF3o0Eol/vtXKobB4pzw5DLuU1z6O71/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzJSux%2FbtsFF3o0Eol%2FvtXKobB4pzw5DLuU1z6O71%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;674&quot; height=&quot;262&quot; data-origin-width=&quot;674&quot; data-origin-height=&quot;262&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. 도달할 수 있는 객체면 true 마크&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;674&quot; data-origin-height=&quot;262&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clQqZP/btsFFKiTWLh/1DXEJuwX8Y1JzS6m6kl7B1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clQqZP/btsFFKiTWLh/1DXEJuwX8Y1JzS6m6kl7B1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clQqZP/btsFFKiTWLh/1DXEJuwX8Y1JzS6m6kl7B1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclQqZP%2FbtsFFKiTWLh%2F1DXEJuwX8Y1JzS6m6kl7B1%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;674&quot; height=&quot;262&quot; data-origin-width=&quot;674&quot; data-origin-height=&quot;262&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;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-origin-width=&quot;674&quot; data-origin-height=&quot;259&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2cT66/btsFEMu4OJx/8wCPYEZiQjgxqKBp8ErIDk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2cT66/btsFEMu4OJx/8wCPYEZiQjgxqKBp8ErIDk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2cT66/btsFEMu4OJx/8wCPYEZiQjgxqKBp8ErIDk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2cT66%2FbtsFEMu4OJx%2F8wCPYEZiQjgxqKBp8ErIDk%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;674&quot; height=&quot;259&quot; data-origin-width=&quot;674&quot; data-origin-height=&quot;259&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순환참조 문제를 제어할 수 있고 무한루프 문제 해결&lt;/p&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;b&gt;단점&lt;/b&gt;&lt;br /&gt;&lt;br /&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;&lt;br /&gt;그러나 이 알고리즘은 &lt;b&gt;프로그램이&lt;/b&gt;&amp;nbsp;&lt;b&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;단점&lt;/b&gt;이&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;성능을&amp;nbsp;제공하도록&amp;nbsp;노력하고&amp;nbsp;있습니다.&lt;/p&gt;</description>
      <category>javascript</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/206</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BD%9C%EB%A0%89%EC%85%98#entry206comment</comments>
      <pubDate>Sun, 10 Mar 2024 22:53:44 +0900</pubDate>
    </item>
    <item>
      <title>지속가능한 컴포넌트 Effective Component</title>
      <link>https://hmk1022.tistory.com/entry/%EC%A7%80%EC%86%8D%EA%B0%80%EB%8A%A5%ED%95%9C-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-Effective-Component</link>
      <description>&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;&lt;/p&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;수정이&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;과정에서&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;있습니다.&lt;br /&gt;&lt;br /&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;&lt;/p&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;사용자의&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;찾고,&amp;nbsp;그에&amp;nbsp;맞게&amp;nbsp;제품을&amp;nbsp;개선하는&amp;nbsp;데&amp;nbsp;중요한&amp;nbsp;역할을&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;고객의&amp;nbsp;니즈는&amp;nbsp;기회로&amp;nbsp;여겨져야&amp;nbsp;합니다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&amp;nbsp;빠르게&amp;nbsp;변화하는&amp;nbsp;환경에서는&amp;nbsp;사용자의&amp;nbsp;니즈를&amp;nbsp;정확히&amp;nbsp;예측하기&amp;nbsp;어렵습니다.&amp;nbsp;따라서&amp;nbsp;&lt;b&gt;변경을&amp;nbsp;예측하지&amp;nbsp;않고&amp;nbsp;유연하게&amp;nbsp;대응&lt;/b&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;있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;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;기능이 만들어지면 &quot;적당히&quot; 분리해야 합니다.&lt;/p&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;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCzoa9/btsFFZ75ErP/I0vhmXspBbB3T7JwGwpx70/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCzoa9/btsFFZ75ErP/I0vhmXspBbB3T7JwGwpx70/img.png&quot; data-origin-width=&quot;747&quot; data-origin-height=&quot;480&quot; data-is-animation=&quot;false&quot; style=&quot;width: 48.3782%; margin-right: 10px;&quot; data-widthpercent=&quot;48.95&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCzoa9/btsFFZ75ErP/I0vhmXspBbB3T7JwGwpx70/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCzoa9%2FbtsFFZ75ErP%2FI0vhmXspBbB3T7JwGwpx70%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;747&quot; height=&quot;480&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFhdBL/btsFFQwPqzi/D0IqsYZYvmUupUUCmc2Tak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFhdBL/btsFFQwPqzi/D0IqsYZYvmUupUUCmc2Tak/img.png&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;276&quot; data-is-animation=&quot;false&quot; width=&quot;602&quot; height=&quot;371&quot; style=&quot;width: 50.459%;&quot; data-widthpercent=&quot;51.05&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFhdBL/btsFFQwPqzi/D0IqsYZYvmUupUUCmc2Tak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFhdBL%2FbtsFFQwPqzi%2FD0IqsYZYvmUupUUCmc2Tak%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;276&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의 Item이라는 컴포넌트는 어떤 컴포넌트일까요?&lt;/p&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_1710030837187&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const { filtered, value, index, fetchResponseType } = repoes;

const Results = (
	&amp;lt;ItemLayout id=&quot;fix_scroll&quot;&amp;gt;
		{filtered.map((repo: ItmeType, i: number) =&amp;gt; (
        	&amp;lt;Item 
            	key={`${item_${i}}`}
                index={i}
                curIndex={index}
            	item={repo}
                onClickItem={onClickItem}
            /&amp;gt;
            {currentTargetValue &amp;amp;&amp;amp; (
            	&amp;lt;Item 
                    key={`${item_${filtered.length}}`}
                    index={filtered.length}
                    curIndex={index}
                    item={{
						id: `search_in_google`,
                        name: `github: ${currentTargetValue}`
                    }}
                    onClickItem={onClickItem}
                /&amp;gt;
            )}	
        ))}
    &amp;lt;/ItemLayout&amp;gt;    
)&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 style=&quot;color: #000000;&quot; data-ke-size=&quot;size23&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Headless 기반의 추상화하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변하는 것 vs 상대적으로 변하지 않는 것&lt;/p&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;2. 한 가지 역할만 하기 &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;size16&quot;&gt;&lt;b&gt;3. 도메인 분리하기&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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. Headless UI 기반의 추상화하기&lt;/h4&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;885&quot; data-origin-height=&quot;233&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kGTkx/btsFGA04oc3/0ARPnFKgJfLh2lQu0Micvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kGTkx/btsFGA04oc3/0ARPnFKgJfLh2lQu0Micvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kGTkx/btsFGA04oc3/0ARPnFKgJfLh2lQu0Micvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkGTkx%2FbtsFGA04oc3%2F0ARPnFKgJfLh2lQu0Micvk%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;885&quot; height=&quot;233&quot; data-origin-width=&quot;885&quot; data-origin-height=&quot;233&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;832&quot; data-origin-height=&quot;498&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ucBRi/btsFHprbTT2/6eWP6LnGa68kz1lMuCoZJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ucBRi/btsFHprbTT2/6eWP6LnGa68kz1lMuCoZJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ucBRi/btsFHprbTT2/6eWP6LnGa68kz1lMuCoZJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FucBRi%2FbtsFHprbTT2%2F6eWP6LnGa68kz1lMuCoZJK%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;855&quot; height=&quot;512&quot; data-origin-width=&quot;832&quot; data-origin-height=&quot;498&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;608&quot; data-origin-height=&quot;433&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPU9WQ/btsFGBeCp3i/3A4YIlx3yEHiioT9L8ShVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPU9WQ/btsFGBeCp3i/3A4YIlx3yEHiioT9L8ShVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPU9WQ/btsFGBeCp3i/3A4YIlx3yEHiioT9L8ShVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPU9WQ%2FbtsFGBeCp3i%2F3A4YIlx3yEHiioT9L8ShVK%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;608&quot; height=&quot;433&quot; data-origin-width=&quot;608&quot; data-origin-height=&quot;433&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;p data-ke-size=&quot;size16&quot;&gt;어떻게 보여줄지는 디자인에 의존합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;디자인에 의존하는 UI를 컴포넌트가 관리하는 '데이터'와 분리해 보면 어떨까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;데이터와 디자인 나누기&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;- 달력 데이터에 관련된 것들을 useCalandar 훅으로 나누기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 디자인 부분은 따로 jsx 형태로 마크업&lt;/p&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;UI가 변경되더라도 데이터만 다루는 useCalandar 훅은 변경할 필요가 없어짐&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1091&quot; data-origin-height=&quot;517&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dBJ4mj/btsFFQXUxor/KyrGiLCVDOnHaxzLctvlbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dBJ4mj/btsFFQXUxor/KyrGiLCVDOnHaxzLctvlbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dBJ4mj/btsFFQXUxor/KyrGiLCVDOnHaxzLctvlbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdBJ4mj%2FbtsFFQXUxor%2FKyrGiLCVDOnHaxzLctvlbK%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;1091&quot; height=&quot;517&quot; data-origin-width=&quot;1091&quot; data-origin-height=&quot;517&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;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 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;474&quot; data-origin-height=&quot;452&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxnmKj/btsFHqXYPyu/kAqQOwJ5TLk9pRWGryU63K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxnmKj/btsFHqXYPyu/kAqQOwJ5TLk9pRWGryU63K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxnmKj/btsFHqXYPyu/kAqQOwJ5TLk9pRWGryU63K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxnmKj%2FbtsFHqXYPyu%2FkAqQOwJ5TLk9pRWGryU63K%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;474&quot; height=&quot;452&quot; data-origin-width=&quot;474&quot; data-origin-height=&quot;452&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;상호작용하는 이벤트 핸들러들을 useLongPress라는 훅으로 분리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hooks로부터 반환하는 값을 longPressProps를 주입하는 형태로 변경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상호작용하는 부분의 관심사가 분리되고, 다른 컴포넌트에서도 longPress 동작을 정의할 때 재사용도 용이해짐&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;472&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUitaO/btsFGmaWjmh/lxyLC2Dj4YCUmQ11Kzx0aK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUitaO/btsFGmaWjmh/lxyLC2Dj4YCUmQ11Kzx0aK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUitaO/btsFGmaWjmh/lxyLC2Dj4YCUmQ11Kzx0aK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUitaO%2FbtsFGmaWjmh%2FlxyLC2Dj4YCUmQ11Kzx0aK%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;446&quot; height=&quot;472&quot; data-origin-width=&quot;446&quot; data-origin-height=&quot;472&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;h3 data-ke-size=&quot;size23&quot;&gt;2. 한 가지 역할만 하기 (Composition)&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;아래는 흔하게 볼 수 있는 Select 컴포넌트인데요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 UI를 만들다 보면 자연스럽게 작은 컴포넌트로 구성해서 만들게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;333&quot; data-origin-height=&quot;371&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C5fVK/btsFE331iGZ/tSwMhGibj6CQo9Bk3CCqvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C5fVK/btsFE331iGZ/tSwMhGibj6CQo9Bk3CCqvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C5fVK/btsFE331iGZ/tSwMhGibj6CQo9Bk3CCqvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC5fVK%2FbtsFE331iGZ%2FtSwMhGibj6CQo9Bk3CCqvK%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;333&quot; height=&quot;371&quot; data-origin-width=&quot;333&quot; data-origin-height=&quot;371&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;&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;당장 label 디자인만 변경되더라도 재사용하기 어렵습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;501&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d75tn5/btsFDDdUWU5/o2LbqQVqFKEvyZXVoZ2nRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d75tn5/btsFDDdUWU5/o2LbqQVqFKEvyZXVoZ2nRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d75tn5/btsFDDdUWU5/o2LbqQVqFKEvyZXVoZ2nRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd75tn5%2FbtsFDDdUWU5%2Fo2LbqQVqFKEvyZXVoZ2nRK%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;637&quot; height=&quot;501&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;501&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;p data-ke-size=&quot;size18&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;담당하고 있는 데이터와 역할을 기준으로 분리&lt;/p&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. 메뉴의 노출 여부를 관리하는 상태인 isOpen을 분리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. isOpen의 상태를 바꾸기 위한 상호작용을 Dropdown.Trigger로 분리&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 옵션영역을 Dropdown.menu로 구성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 메뉴를 구성하는 각각 Item을 분리&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;744&quot; data-origin-height=&quot;446&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KBBDC/btsFF573QsQ/Ajl9nSX1HSjUgKuENDkxF1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KBBDC/btsFF573QsQ/Ajl9nSX1HSjUgKuENDkxF1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KBBDC/btsFF573QsQ/Ajl9nSX1HSjUgKuENDkxF1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKBBDC%2FbtsFF573QsQ%2FAjl9nSX1HSjUgKuENDkxF1%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;744&quot; height=&quot;446&quot; data-origin-width=&quot;744&quot; data-origin-height=&quot;446&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;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;Select 컴포넌트와 trigger로 전달한 InputButton 컴포넌트는 서로의 존재에 대해 알지 못한다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2Ev47/btsFDFCMupR/eWkzSF5I0ZT2lGwxmhy3t0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2Ev47/btsFDFCMupR/eWkzSF5I0ZT2lGwxmhy3t0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2Ev47/btsFDFCMupR/eWkzSF5I0ZT2lGwxmhy3t0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2Ev47%2FbtsFDFCMupR%2FeWkzSF5I0ZT2lGwxmhy3t0%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;836&quot; height=&quot;436&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;436&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;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;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;&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;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;&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 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-origin-width=&quot;894&quot; data-origin-height=&quot;511&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1RCEt/btsFFYnRfZP/S3cRqiRFogKInmTKGuykGK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1RCEt/btsFFYnRfZP/S3cRqiRFogKInmTKGuykGK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1RCEt/btsFFYnRfZP/S3cRqiRFogKInmTKGuykGK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1RCEt%2FbtsFFYnRfZP%2FS3cRqiRFogKInmTKGuykGK%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;894&quot; height=&quot;511&quot; data-origin-width=&quot;894&quot; data-origin-height=&quot;511&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;p data-ke-size=&quot;size16&quot;&gt;Trigger 부분만 수정하고 싶으면 분리된 Trigger만 수정하면 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;560&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oyWuk/btsFEgXkuac/oUfCBKJ1jYd2cB76uWf2UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oyWuk/btsFEgXkuac/oUfCBKJ1jYd2cB76uWf2UK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oyWuk/btsFEgXkuac/oUfCBKJ1jYd2cB76uWf2UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoyWuk%2FbtsFEgXkuac%2FoUfCBKJ1jYd2cB76uWf2UK%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;1168&quot; height=&quot;560&quot; data-origin-width=&quot;1168&quot; data-origin-height=&quot;560&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;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. 도메인 분리하기&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;&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;- 컴포넌트의 이름과 props 네이밍은 일반적인 컨벤션으로 작성하자&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;539&quot; data-origin-height=&quot;277&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqzHXr/btsFE1ZtdId/mUK4p9zSKiLwLousaDYQW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqzHXr/btsFE1ZtdId/mUK4p9zSKiLwLousaDYQW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqzHXr/btsFE1ZtdId/mUK4p9zSKiLwLousaDYQW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqzHXr%2FbtsFE1ZtdId%2FmUK4p9zSKiLwLousaDYQW0%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;539&quot; height=&quot;277&quot; data-origin-width=&quot;539&quot; data-origin-height=&quot;277&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;프론트엔드 개발자라면 Select가 어떻게 동작하는지 알고 있고,&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;UI 로직만 위임하는 방식으로 볼 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;473&quot; data-origin-height=&quot;270&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nbS8U/btsFF6FT35Y/N7GJHfoyrTMLout26kqPNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nbS8U/btsFF6FT35Y/N7GJHfoyrTMLout26kqPNK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nbS8U/btsFF6FT35Y/N7GJHfoyrTMLout26kqPNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnbS8U%2FbtsFF6FT35Y%2FN7GJHfoyrTMLout26kqPNK%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;270&quot; data-origin-width=&quot;473&quot; data-origin-height=&quot;270&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;h4 data-ke-size=&quot;size20&quot;&gt;컴포넌트를 설계하는 순서&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;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;&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;608&quot; data-origin-height=&quot;581&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vT7d9/btsFHpELaXu/xKjwISa0TkTUFbDbzKDbu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vT7d9/btsFHpELaXu/xKjwISa0TkTUFbDbzKDbu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vT7d9/btsFHpELaXu/xKjwISa0TkTUFbDbzKDbu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvT7d9%2FbtsFHpELaXu%2FxKjwISa0TkTUFbDbzKDbu1%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;608&quot; height=&quot;581&quot; data-origin-width=&quot;608&quot; data-origin-height=&quot;581&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 컴포넌트를 나누는 이유 생각해보기&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;&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;766&quot; data-origin-height=&quot;563&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Wc5CL/btsFD3i6v8J/YNbJ3oh4pM2gAEBB87jHH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Wc5CL/btsFD3i6v8J/YNbJ3oh4pM2gAEBB87jHH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Wc5CL/btsFD3i6v8J/YNbJ3oh4pM2gAEBB87jHH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWc5CL%2FbtsFD3i6v8J%2FYNbJ3oh4pM2gAEBB87jHH0%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;766&quot; height=&quot;563&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;563&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;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Reference&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;a href=&quot;https://www.youtube.com/watch?v=fR8tsJ2r7Eg&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=fR8tsJ2r7Eg&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/205</guid>
      <comments>https://hmk1022.tistory.com/entry/%EC%A7%80%EC%86%8D%EA%B0%80%EB%8A%A5%ED%95%9C-%EC%BB%B4%ED%8F%AC%EB%84%8C%ED%8A%B8-Effective-Component#entry205comment</comments>
      <pubDate>Sun, 10 Mar 2024 12:58:42 +0900</pubDate>
    </item>
    <item>
      <title>프론트엔드 클린코드(클린 코드 != 짧은 코드)</title>
      <link>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%ED%81%B4%EB%A6%B0%EC%BD%94%EB%93%9C%ED%81%B4%EB%A6%B0-%EC%BD%94%EB%93%9C-%EC%A7%A7%EC%9D%80-%EC%BD%94%EB%93%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이 글은 토스 SLASH21의 실무에서 바로 쓰는 Frontend Clean Code를 바탕으로 작성된 글이며&lt;br /&gt;클린코드에 대한 관점은 개인마다 다를 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size16&quot; data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;클린코드를 해야 하는 이유&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;실무에서 클린 코드 = 유지보수 시간의 단축&lt;br /&gt;&lt;br /&gt;&lt;b&gt;시간 = 자원 = 돈&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 클린 했다. =&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;하지만, 기존 코드에 기능을 추가하는 상황이라면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무의 대부분은 새로운 기능을 만드는 경우도 있겠지만, 기존의 코드에 새로운 기능을 추가하는 경우가 더 많다.&lt;br /&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;- &lt;b&gt;설계사가 있는 경우엔 설계사 사진이 들어간 팝업을 먼저 띄워달라는 추가 기능&lt;/b&gt;을 요청받음&lt;/p&gt;
&lt;pre id=&quot;code_1709955850638&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function QuestionPage() {

	const [popupOpend, setPopupOpened] = useState(false);
    
	// 질문 등록 핸들러 함수
	async function handleQuestionSubmit() {
    	const 연결전문가 = await 연결전문가_받아오기();
        
        // 기능 추가받은 연결 전문가가 있는지 검사 분기처리
        if(연결전문가 !== null){
        	setPopupOpened(true);
        } else {
        	const 약관동의 = await 약관동의_받아오기();
            
            if(!약관동의){
				await 약관동의_팝업열기();
            }
            
            // 질문전송 성공 시 성공 alert
            await 질문전송(questionValue);
            alert(&quot;질문이 등록되었어요.&quot;);
        }
    }
    
    
    async function handleMyExpertQuestionSubmit() {
		await 연결전문가_질문전송(questionValue, 연결전문가.id);
        alert(`${연결전문가.name}에게 질문이 등록되었어요.`)
    }

	return (
    	&amp;lt;main&amp;gt;
        	&amp;lt;form&amp;gt;
        		&amp;lt;textarea placeholder=&quot;어떤 내용이 궁금한가요?&quot; /&amp;gt;
                &amp;lt;button onClick={handleQuestionSubmit}&amp;gt;질문하기&amp;lt;/button&amp;gt;
            &amp;lt;/form&amp;gt;
            {popupOpened &amp;amp;&amp;amp; (
                &amp;lt;연결전문가팝업 onSubmit={handleMyExpertQuestionSubmit}/&amp;gt;
            )}
        &amp;lt;/main&amp;gt;
    )
}&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;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;1. 하나의 목적인 코드가 흩뿌려져 있다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초록색으로 강조된 부분은 &quot;연결 중인 전문가&quot; 팝업 관련된 코드인데,&lt;/p&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-origin-width=&quot;814&quot; data-origin-height=&quot;477&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y3mge/btsFENUIpBN/tPogrtoSSeYbBw5zmsCHvK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y3mge/btsFENUIpBN/tPogrtoSSeYbBw5zmsCHvK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y3mge/btsFENUIpBN/tPogrtoSSeYbBw5zmsCHvK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy3mge%2FbtsFENUIpBN%2FtPogrtoSSeYbBw5zmsCHvK%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;814&quot; height=&quot;477&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;477&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;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;3. 하나 함수가 여러 가지 일을 처리하고 있음&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;- handleQuestionSubmit&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- handleMyExpertQuestionSubmit&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;handleQuestionSubmit은 질문 전송 이외에도 여러 가지 일을 하고 있어 읽을 때 어지럽다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;891&quot; data-origin-height=&quot;481&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b72mKZ/btsFDEwXha3/2Keu8XadgqFKS7XihMLuyK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b72mKZ/btsFDEwXha3/2Keu8XadgqFKS7XihMLuyK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b72mKZ/btsFDEwXha3/2Keu8XadgqFKS7XihMLuyK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb72mKZ%2FbtsFDEwXha3%2F2Keu8XadgqFKS7XihMLuyK%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;891&quot; height=&quot;481&quot; data-origin-width=&quot;891&quot; data-origin-height=&quot;481&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;h4 data-ke-size=&quot;size20&quot;&gt;3. 함수 세부 구현단계가 제각각&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;484&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sN5Pp/btsFEtPe3dL/3bnEKFYYhKuXGA7Hy4GC9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sN5Pp/btsFEtPe3dL/3bnEKFYYhKuXGA7Hy4GC9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sN5Pp/btsFEtPe3dL/3bnEKFYYhKuXGA7Hy4GC9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsN5Pp%2FbtsFEtPe3dL%2F3bnEKFYYhKuXGA7Hy4GC9K%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;862&quot; height=&quot;484&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;484&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&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;/p&gt;
&lt;p data-ke-size=&quot;size18&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;&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;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;- handleNewExpertQuestionSubmit =&amp;gt; 새로운 전문가에게 연결하는 로직만 넣음&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;- handleMyExpertQuestionSubmit =&amp;gt; 연결 중인 전문가에게 질문하는 로직만 넣기&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&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-origin-width=&quot;820&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dPG6SV/btsFEjM3xTn/QfcG1GO61swBPKvQs5oIWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dPG6SV/btsFEjM3xTn/QfcG1GO61swBPKvQs5oIWK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dPG6SV/btsFEjM3xTn/QfcG1GO61swBPKvQs5oIWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdPG6SV%2FbtsFEjM3xTn%2FQfcG1GO61swBPKvQs5oIWK%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;820&quot; height=&quot;412&quot; data-origin-width=&quot;820&quot; data-origin-height=&quot;412&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;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 data-ke-size=&quot;size16&quot;&gt;기존에는 팝업을 여는 버튼과 팝업 코드가 동떨어져 있었는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 모아서 &quot;PopupTriggerButton&quot; 이란 컴포넌틑를 만들었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;826&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zuYuk/btsFF9CtbCg/K3COzZoFkVKRR5B9cpFdK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zuYuk/btsFF9CtbCg/K3COzZoFkVKRR5B9cpFdK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zuYuk/btsFF9CtbCg/K3COzZoFkVKRR5B9cpFdK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzuYuk%2FbtsFF9CtbCg%2FK3COzZoFkVKRR5B9cpFdK1%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;826&quot; height=&quot;392&quot; data-origin-width=&quot;826&quot; data-origin-height=&quot;392&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;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;833&quot; data-origin-height=&quot;400&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btcszO/btsFDE4NiuA/Od8xVunrcL3AHIsMrLM8Q0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btcszO/btsFDE4NiuA/Od8xVunrcL3AHIsMrLM8Q0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btcszO/btsFDE4NiuA/Od8xVunrcL3AHIsMrLM8Q0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtcszO%2FbtsFDE4NiuA%2FOd8xVunrcL3AHIsMrLM8Q0%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;833&quot; height=&quot;400&quot; data-origin-width=&quot;833&quot; data-origin-height=&quot;400&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;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;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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;원하는&amp;nbsp; 로직을 빠르게 찾으려면?&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;응집도 - 하나의 목적을 가진 코드가 흩뿌려져 있지 않게 하기&lt;/p&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;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;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;828&quot; data-origin-height=&quot;399&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPNlGv/btsFE6lYcNd/WHBZ94Fs81b2s99iqT2P51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPNlGv/btsFE6lYcNd/WHBZ94Fs81b2s99iqT2P51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPNlGv/btsFE6lYcNd/WHBZ94Fs81b2s99iqT2P51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPNlGv%2FbtsFE6lYcNd%2FWHBZ94Fs81b2s99iqT2P51%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;828&quot; height=&quot;399&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;399&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;그런데, 이게 좋은 방법일까?&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-origin-width=&quot;825&quot; data-origin-height=&quot;398&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9Ob9n/btsFFmJkBUv/CgaY79ccp8ZNPKkb8pYn40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9Ob9n/btsFFmJkBUv/CgaY79ccp8ZNPKkb8pYn40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9Ob9n/btsFFmJkBUv/CgaY79ccp8ZNPKkb8pYn40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9Ob9n%2FbtsFFmJkBUv%2FCgaY79ccp8ZNPKkb8pYn40%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;825&quot; height=&quot;398&quot; data-origin-width=&quot;825&quot; data-origin-height=&quot;398&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;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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;868&quot; data-origin-height=&quot;508&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kyTas/btsFGSmIpMB/AZy5cyZL5kOGCZsdJvuFm0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kyTas/btsFGSmIpMB/AZy5cyZL5kOGCZsdJvuFm0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kyTas/btsFGSmIpMB/AZy5cyZL5kOGCZsdJvuFm0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkyTas%2FbtsFGSmIpMB%2FAZy5cyZL5kOGCZsdJvuFm0%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;809&quot; height=&quot;473&quot; data-origin-width=&quot;868&quot; data-origin-height=&quot;508&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;p data-ke-size=&quot;size16&quot;&gt;어떻게 해야 읽기 좋게 응집할 수 있을까?&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;/h4&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;405&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m5CfV/btsFCzCFQbb/OTFie4kQeX4q5OFpBTT5mK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m5CfV/btsFCzCFQbb/OTFie4kQeX4q5OFpBTT5mK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m5CfV/btsFCzCFQbb/OTFie4kQeX4q5OFpBTT5mK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm5CfV%2FbtsFCzCFQbb%2FOTFie4kQeX4q5OFpBTT5mK%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;405&quot; data-origin-width=&quot;813&quot; data-origin-height=&quot;405&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;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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;834&quot; data-origin-height=&quot;441&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dx1yvB/btsFFOS6Ris/dx2OyZtfIttvQKtlJ1QR1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dx1yvB/btsFFOS6Ris/dx2OyZtfIttvQKtlJ1QR1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dx1yvB/btsFFOS6Ris/dx2OyZtfIttvQKtlJ1QR1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdx1yvB%2FbtsFFOS6Ris%2Fdx2OyZtfIttvQKtlJ1QR1k%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;834&quot; height=&quot;441&quot; data-origin-width=&quot;834&quot; data-origin-height=&quot;441&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;h4 data-ke-size=&quot;size20&quot;&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;openPopup이라는 커스텀훅에 모든 코드를 다 숨기는 게 아니라,&lt;/p&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;830&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWgPFA/btsFFKXfRmq/YqOpiktcOrK8GVlUuwKi20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWgPFA/btsFFKXfRmq/YqOpiktcOrK8GVlUuwKi20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWgPFA/btsFFKXfRmq/YqOpiktcOrK8GVlUuwKi20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWgPFA%2FbtsFFKXfRmq%2FYqOpiktcOrK8GVlUuwKi20%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;830&quot; height=&quot;420&quot; data-origin-width=&quot;830&quot; data-origin-height=&quot;420&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;/h4&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;&quot;선언적 프로그래밍&quot;이라고 한다.&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;904&quot; data-origin-height=&quot;510&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQpARB/btsFDUtd5DV/6BzrHzTVB0UdmpCPoAtkb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQpARB/btsFDUtd5DV/6BzrHzTVB0UdmpCPoAtkb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQpARB/btsFDUtd5DV/6BzrHzTVB0UdmpCPoAtkb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQpARB%2FbtsFDUtd5DV%2F6BzrHzTVB0UdmpCPoAtkb0%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;904&quot; height=&quot;510&quot; data-origin-width=&quot;904&quot; data-origin-height=&quot;510&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;p data-ke-size=&quot;size18&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;880&quot; data-origin-height=&quot;326&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yDzDo/btsFFPR1ZiQ/YIKLD45cIx92a2rsGVpGwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yDzDo/btsFFPR1ZiQ/YIKLD45cIx92a2rsGVpGwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yDzDo/btsFFPR1ZiQ/YIKLD45cIx92a2rsGVpGwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyDzDo%2FbtsFFPR1ZiQ%2FYIKLD45cIx92a2rsGVpGwK%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;880&quot; height=&quot;326&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;326&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;872&quot; data-origin-height=&quot;317&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwLB1a/btsFFQwD2zM/MmEQ1vUUo6pCjqlNvKH0wk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwLB1a/btsFFQwD2zM/MmEQ1vUUo6pCjqlNvKH0wk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwLB1a/btsFFQwD2zM/MmEQ1vUUo6pCjqlNvKH0wk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwLB1a%2FbtsFFQwD2zM%2FMmEQ1vUUo6pCjqlNvKH0wk%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;872&quot; height=&quot;317&quot; data-origin-width=&quot;872&quot; data-origin-height=&quot;317&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;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;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;읽는데 오래 걸리고 재사용하기 어렵다는 단점이 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/V4JDd/btsFDyXO5ba/N8YyiXfSHuIKNd6kQ9JBS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/V4JDd/btsFDyXO5ba/N8YyiXfSHuIKNd6kQ9JBS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/V4JDd/btsFDyXO5ba/N8YyiXfSHuIKNd6kQ9JBS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FV4JDd%2FbtsFDyXO5ba%2FN8YyiXfSHuIKNd6kQ9JBS1%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;873&quot; height=&quot;320&quot; data-origin-width=&quot;873&quot; data-origin-height=&quot;320&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;h4 data-ke-size=&quot;size20&quot;&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;리액트를 사용하면 HTML에도 선언형 프로그래밍을 이용할 수 있지만,&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;&amp;nbsp;&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;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;단순하게 &quot;질문제출&quot; 정도로 함수이름을 정의할까?&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;337&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuKQ4a/btsFEwd8YSA/9AgRD4ZJS9xhuiWSSy6In0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuKQ4a/btsFEwd8YSA/9AgRD4ZJS9xhuiWSSy6In0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuKQ4a/btsFEwd8YSA/9AgRD4ZJS9xhuiWSSy6In0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuKQ4a%2FbtsFEwd8YSA%2F9AgRD4ZJS9xhuiWSSy6In0%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;578&quot; height=&quot;337&quot; data-origin-width=&quot;578&quot; data-origin-height=&quot;337&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;p data-ke-size=&quot;size16&quot;&gt;이러한 기능추가가 반복되고 함수 이름과 다른 기능을 하는 경우가 빈번해지면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드에 대한 신뢰가 떨어지고 유지보수에 대한 리소스가 더 증가하게 된다 =&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;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;단일 책임의 원칙을 적용해 함수가 하나의 책임만 가지게 하도록 해보자&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;648&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FmdlC/btsFF1xHf0w/pkhftn8kofzKxGwRS0FuH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FmdlC/btsFF1xHf0w/pkhftn8kofzKxGwRS0FuH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FmdlC/btsFF1xHf0w/pkhftn8kofzKxGwRS0FuH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFmdlC%2FbtsFF1xHf0w%2Fpkhftn8kofzKxGwRS0FuH0%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;648&quot; height=&quot;612&quot; data-origin-width=&quot;648&quot; data-origin-height=&quot;612&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;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;IntersectionObserver를 이용해 요소가 겹쳐 있을 때, 함수를 실행시키는 코드를&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;IntersectionArea라는 컴포넌트로 나눠 세부 구현은 숨기고, 사용하는 입장에서 Impression 시&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;918&quot; data-origin-height=&quot;626&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCVRO5/btsFHsafo0y/19h15yNIHhUYAAClpHOnw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCVRO5/btsFHsafo0y/19h15yNIHhUYAAClpHOnw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCVRO5/btsFHsafo0y/19h15yNIHhUYAAClpHOnw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCVRO5%2FbtsFHsafo0y%2F19h15yNIHhUYAAClpHOnw0%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;729&quot; height=&quot;497&quot; data-origin-width=&quot;918&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;도메인 지식이 복잡하게 들어가거나,&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;871&quot; data-origin-height=&quot;529&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brsgGX/btsFEOlMl84/KJN6zjVdlJcKgZsgaelCjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brsgGX/btsFEOlMl84/KJN6zjVdlJcKgZsgaelCjk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brsgGX/btsFEOlMl84/KJN6zjVdlJcKgZsgaelCjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrsgGX%2FbtsFEOlMl84%2FKJN6zjVdlJcKgZsgaelCjk%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;796&quot; height=&quot;483&quot; data-origin-width=&quot;871&quot; data-origin-height=&quot;529&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;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;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;- 오른쪽은 선언적으로 팝업의 &quot;제출&quot;, &quot;성공&quot; 액션으로 나누고 나머지는 추상화시킴&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;425&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qjRNQ/btsFFMHxOkP/FWhNfhIKKP4rMNbHkPKAR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qjRNQ/btsFFMHxOkP/FWhNfhIKKP4rMNbHkPKAR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qjRNQ/btsFFMHxOkP/FWhNfhIKKP4rMNbHkPKAR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqjRNQ%2FbtsFFMHxOkP%2FFWhNfhIKKP4rMNbHkPKAR0%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;876&quot; height=&quot;425&quot; data-origin-width=&quot;876&quot; data-origin-height=&quot;425&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;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;함수 모듈로 분리해 getPlannerLabel 함수명 안에 추상화시킴&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;448&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xEvVB/btsFGSttNGL/qsQiGZZg0GKCaNRdbK6onk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xEvVB/btsFGSttNGL/qsQiGZZg0GKCaNRdbK6onk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xEvVB/btsFGSttNGL/qsQiGZZg0GKCaNRdbK6onk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxEvVB%2FbtsFGSttNGL%2FqsQiGZZg0GKCaNRdbK6onk%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;882&quot; height=&quot;448&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;448&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;p data-ke-size=&quot;size18&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-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;432&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwe2Hs/btsFGpkN5dl/X0SzT1b9rd0c4jYC6yAYO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwe2Hs/btsFGpkN5dl/X0SzT1b9rd0c4jYC6yAYO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwe2Hs/btsFGpkN5dl/X0SzT1b9rd0c4jYC6yAYO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbwe2Hs%2FbtsFGpkN5dl%2FX0SzT1b9rd0c4jYC6yAYO0%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;865&quot; height=&quot;432&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;432&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;p data-ke-size=&quot;size16&quot;&gt;버튼을 눌렀을때 컨펌을 보여주는 기능을 ConfirmButton이라는 컴포넌트로 추상화&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;430&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvHzEP/btsFGCYIQ91/0w3TwOtf0rK6vsTrnaTUL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvHzEP/btsFGCYIQ91/0w3TwOtf0rK6vsTrnaTUL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvHzEP/btsFGCYIQ91/0w3TwOtf0rK6vsTrnaTUL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvHzEP%2FbtsFGCYIQ91%2F0w3TwOtf0rK6vsTrnaTUL1%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;858&quot; height=&quot;430&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;430&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;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;858&quot; data-origin-height=&quot;417&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Bkp8z/btsFFKCYypl/e5Z8iyRpUEjAKcq4qHtkgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Bkp8z/btsFFKCYypl/e5Z8iyRpUEjAKcq4qHtkgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Bkp8z/btsFFKCYypl/e5Z8iyRpUEjAKcq4qHtkgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBkp8z%2FbtsFFKCYypl%2Fe5Z8iyRpUEjAKcq4qHtkgK%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;858&quot; height=&quot;417&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;417&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;p data-ke-size=&quot;size16&quot;&gt;모든 기능을 모두 ConfirmButton이라는 이름아래에 추상화시킬 수도 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;879&quot; data-origin-height=&quot;415&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Frrkm/btsFGTzaltf/dEXecBKKCwitB5nWLZBvBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Frrkm/btsFGTzaltf/dEXecBKKCwitB5nWLZBvBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Frrkm/btsFGTzaltf/dEXecBKKCwitB5nWLZBvBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFrrkm%2FbtsFGTzaltf%2FdEXecBKKCwitB5nWLZBvBk%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;879&quot; height=&quot;415&quot; data-origin-width=&quot;879&quot; data-origin-height=&quot;415&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;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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;872&quot; data-origin-height=&quot;610&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cnJmlr/btsFFKQvtLL/ExxPHKqS5SkmankX7OaUQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cnJmlr/btsFFKQvtLL/ExxPHKqS5SkmankX7OaUQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnJmlr/btsFFKQvtLL/ExxPHKqS5SkmankX7OaUQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnJmlr%2FbtsFFKQvtLL%2FExxPHKqS5SkmankX7OaUQK%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;872&quot; height=&quot;610&quot; data-origin-width=&quot;872&quot; data-origin-height=&quot;610&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;641&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AVhI1/btsFGDQSgdC/dz7EfEaTQOb0Kk8BRPkpG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AVhI1/btsFGDQSgdC/dz7EfEaTQOb0Kk8BRPkpG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AVhI1/btsFGDQSgdC/dz7EfEaTQOb0Kk8BRPkpG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAVhI1%2FbtsFGDQSgdC%2Fdz7EfEaTQOb0Kk8BRPkpG0%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;857&quot; height=&quot;641&quot; data-origin-width=&quot;857&quot; data-origin-height=&quot;641&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;p data-ke-size=&quot;size18&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;524&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqmZzb/btsFFXhZe6T/EXL91MZHUvBG6L9BYxhwF0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqmZzb/btsFFXhZe6T/EXL91MZHUvBG6L9BYxhwF0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqmZzb/btsFFXhZe6T/EXL91MZHUvBG6L9BYxhwF0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqmZzb%2FbtsFFXhZe6T%2FEXL91MZHUvBG6L9BYxhwF0%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;524&quot; height=&quot;513&quot; data-origin-width=&quot;524&quot; data-origin-height=&quot;513&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;459&quot; data-origin-height=&quot;518&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rbktP/btsFE3CK8Xr/ouswggYKinxDtodXDb8JRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rbktP/btsFE3CK8Xr/ouswggYKinxDtodXDb8JRK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rbktP/btsFE3CK8Xr/ouswggYKinxDtodXDb8JRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrbktP%2FbtsFE3CK8Xr%2FouswggYKinxDtodXDb8JRK%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;459&quot; height=&quot;518&quot; data-origin-width=&quot;459&quot; data-origin-height=&quot;518&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;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;클린 코드에 대한 의견은&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;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;기존에 널리 알려진 컨벤션 ex) SOLID&lt;br /&gt;&lt;br /&gt;+&lt;br /&gt;&lt;br /&gt;팀원과 함께 명시적으로 잘 정해진 약속, 컨벤션 기반&lt;/span&gt;&lt;/span&gt;&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;&lt;br /&gt;답은 없고 조직마다 처리해야 하는 업무량도 다르겠지만,&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;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;Reference&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;a href=&quot;https://www.youtube.com/watch?v=edWbHp_k_9Y&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.youtube.com/watch?v=edWbHp_k_9Y&lt;/a&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;&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>Front-End</category>
      <author>hmk run dev</author>
      <guid isPermaLink="true">https://hmk1022.tistory.com/204</guid>
      <comments>https://hmk1022.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%ED%81%B4%EB%A6%B0%EC%BD%94%EB%93%9C%ED%81%B4%EB%A6%B0-%EC%BD%94%EB%93%9C-%EC%A7%A7%EC%9D%80-%EC%BD%94%EB%93%9C#entry204comment</comments>
      <pubDate>Sat, 9 Mar 2024 14:01:25 +0900</pubDate>
    </item>
  </channel>
</rss>