<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>nicksoon</title>
    <link>https://nicksoon.tistory.com/</link>
    <description>스타트업에서 개발을 하고 있는 개발자 입니다</description>
    <language>ko</language>
    <pubDate>Sun, 31 May 2026 04:06:40 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>nicksoon</managingEditor>
    <image>
      <title>nicksoon</title>
      <url>https://tistory1.daumcdn.net/tistory/6497473/attach/d6802a12dca24c44a9d15005d0edc87a</url>
      <link>https://nicksoon.tistory.com</link>
    </image>
    <item>
      <title> ️ 생성 패턴(Creational Patterns) 정리표</title>
      <link>https://nicksoon.tistory.com/entry/%F0%9F%9B%A0%EF%B8%8F-%EC%83%9D%EC%84%B1-%ED%8C%A8%ED%84%B4Creational-Patterns-%EC%A0%95%EB%A6%AC%ED%91%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;패턴 이름핵심 개념쉽게 말하면키워드 / 특징&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;927&quot; data-start=&quot;186&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;927&quot; data-start=&quot;406&quot;&gt;
&lt;tr data-end=&quot;512&quot; data-start=&quot;406&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;425&quot; data-start=&quot;406&quot;&gt;&lt;b&gt;Singleton&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;468&quot; data-start=&quot;425&quot;&gt;객체를 오직 하나만 생성&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;490&quot; data-start=&quot;468&quot;&gt;&lt;b&gt;&amp;ldquo;하나만 만들어 써!&amp;rdquo;&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;512&quot; data-start=&quot;490&quot;&gt;전역 인스턴스, 하나의 객체 공유&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;616&quot; data-start=&quot;513&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;534&quot; data-start=&quot;513&quot;&gt;&lt;b&gt;Factory Method&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;573&quot; data-start=&quot;534&quot;&gt;객체 생성은 서브클래스에 맡김&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;593&quot; data-start=&quot;573&quot;&gt;&lt;b&gt;&amp;ldquo;생성은 알아서 해줄게&amp;rdquo;&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;616&quot; data-start=&quot;593&quot;&gt;객체 생성 캡슐화, 서브클래스 결정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;714&quot; data-start=&quot;617&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;640&quot; data-start=&quot;617&quot;&gt;&lt;b&gt;Abstract Factory&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;672&quot; data-start=&quot;640&quot;&gt;관련 객체들 그룹(패밀리)을 생성하는 인터페이스 제공&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;694&quot; data-start=&quot;672&quot;&gt;&lt;b&gt;&amp;ldquo;세트로 만들어줄게&amp;rdquo;&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;714&quot; data-start=&quot;694&quot;&gt;제품군 생성, GUI 테마 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;818&quot; data-start=&quot;715&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;734&quot; data-start=&quot;715&quot;&gt;&lt;b&gt;Builder&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;774&quot; data-start=&quot;734&quot;&gt;복잡한 객체를 단계적으로 생성&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;796&quot; data-start=&quot;774&quot;&gt;&lt;b&gt;&amp;ldquo;조립식으로 만들기&amp;rdquo;&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;818&quot; data-start=&quot;796&quot;&gt;순서대로 조립, 다양한 표현 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;927&quot; data-start=&quot;819&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;838&quot; data-start=&quot;819&quot;&gt;&lt;b&gt;Prototype&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;880&quot; data-start=&quot;838&quot;&gt;기존 객체를 복제해서 생성&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;903&quot; data-start=&quot;880&quot;&gt;&lt;b&gt;&amp;ldquo;복사해서 만들기&amp;rdquo;&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;927&quot; data-start=&quot;903&quot;&gt;clone, 원형 복제, 성능 최적화&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 data-end=&quot;948&quot; data-start=&quot;934&quot; data-ke-size=&quot;size26&quot;&gt;  상황별 요약 예&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1180&quot; data-start=&quot;950&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;988&quot; data-start=&quot;950&quot;&gt;전역으로 하나만 유지해야 하는 설정/객체 &amp;rarr; Singleton&lt;/li&gt;
&lt;li data-end=&quot;1038&quot; data-start=&quot;989&quot;&gt;어떤 객체를 생성할지 모를 때, 하위 클래스에 위임 &amp;rarr; Factory Method&lt;/li&gt;
&lt;li data-end=&quot;1090&quot; data-start=&quot;1039&quot;&gt;&lt;b&gt;같은 계열의 객체들&lt;/b&gt;을 세트로 만들고 싶을 때 &amp;rarr; Abstract Factory&lt;/li&gt;
&lt;li data-end=&quot;1136&quot; data-start=&quot;1091&quot;&gt;&lt;b&gt;복잡한 조립 단계가 필요한 객체&lt;/b&gt;를 만들고 싶을 때 &amp;rarr; Builder&lt;/li&gt;
&lt;li data-end=&quot;1180&quot; data-start=&quot;1137&quot;&gt;기존 객체를 &lt;b&gt;복사해서 빨리 만들고 싶을 때&lt;/b&gt; &amp;rarr; Prototype&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;1185&quot; data-start=&quot;1182&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1198&quot; data-start=&quot;1187&quot; data-ke-size=&quot;size26&quot;&gt;✅ 한 줄 요약&lt;/h2&gt;
&lt;blockquote data-end=&quot;1282&quot; data-start=&quot;1200&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;1282&quot; data-start=&quot;1202&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;생성 패턴&lt;/b&gt; = 객체를 &lt;b&gt;어떻게 만들 것인가&lt;/b&gt;에 대한 패턴!&lt;br /&gt;단순한 생성부터 복잡한 조립까지, 생성 방식을 유연하게 만들어 줘!&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>학점은행제,자격증/정보처리기사 공부</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/144</guid>
      <comments>https://nicksoon.tistory.com/entry/%F0%9F%9B%A0%EF%B8%8F-%EC%83%9D%EC%84%B1-%ED%8C%A8%ED%84%B4Creational-Patterns-%EC%A0%95%EB%A6%AC%ED%91%9C#entry144comment</comments>
      <pubDate>Fri, 25 Jul 2025 16:20:36 +0900</pubDate>
    </item>
    <item>
      <title>✅ HTTP DELETE 요청, 어떤 방식이 정답일까?</title>
      <link>https://nicksoon.tistory.com/entry/%E2%9C%85-HTTP-DELETE-%EC%9A%94%EC%B2%AD-%EC%96%B4%EB%96%A4-%EB%B0%A9%EC%8B%9D%EC%9D%B4-%EC%A0%95%EB%8B%B5%EC%9D%BC%EA%B9%8C</link>
      <description>&lt;h3 data-end=&quot;251&quot; data-start=&quot;202&quot; data-ke-size=&quot;size23&quot;&gt;― 경로(Path), 쿼리(Query), 바디(Body) 각각의 의미와 실무 활용&lt;/h3&gt;
&lt;p data-end=&quot;343&quot; data-start=&quot;253&quot; data-ke-size=&quot;size16&quot;&gt;RESTful API를 설계하다 보면 DELETE 요청을 통해 리소스를 삭제하는 기능을 자주 만들게 됩니다. 이때 가장 흔히 마주치는 질문은 다음과 같습니다:&lt;/p&gt;
&lt;blockquote data-end=&quot;418&quot; data-start=&quot;345&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;418&quot; data-start=&quot;347&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;삭제할 ID는 어디에 담아야 하지? 경로? 쿼리? 바디?&quot;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&quot;여러 개를 삭제할 때는 어떻게 해야 하지?&quot;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;532&quot; data-start=&quot;420&quot; data-ke-size=&quot;size16&quot;&gt;이 글에서는 DELETE 요청에서 데이터를 전달하는 방식들에 대해 정리하고, 제가 직접 겪은 **복수 항목 삭제 사례(rabmidx 여러 개 삭제)**를 기준으로 어떤 방식이 적합한지 공유해보겠습니다.&lt;/p&gt;
&lt;hr data-end=&quot;537&quot; data-start=&quot;534&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;567&quot; data-start=&quot;539&quot; data-ke-size=&quot;size26&quot;&gt;1. DELETE 요청에서의 데이터 전달 방식&lt;/h2&gt;
&lt;h3 data-end=&quot;600&quot; data-start=&quot;569&quot; data-ke-size=&quot;size23&quot;&gt;✅ 1.1 URL 경로(Path Variable)&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;http&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;복사&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;DELETE /users/123 &lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;699&quot; data-start=&quot;631&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;647&quot; data-start=&quot;631&quot;&gt;가장 권장되는 방식입니다.&lt;/li&gt;
&lt;li data-end=&quot;699&quot; data-start=&quot;648&quot;&gt;&lt;b&gt;단일 리소스를 삭제&lt;/b&gt;할 때 가장 명확하며, RESTful한 설계 원칙에 부합합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;735&quot; data-start=&quot;701&quot; data-ke-size=&quot;size23&quot;&gt;✅ 1.2 쿼리 파라미터(Query Parameter)&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;http&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;복사&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;DELETE /users?user_id=123 &lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;868&quot; data-start=&quot;774&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;801&quot; data-start=&quot;774&quot;&gt;가능은 하지만 일반적으로는 권장되지 않습니다.&lt;/li&gt;
&lt;li data-end=&quot;833&quot; data-start=&quot;802&quot;&gt;의도나 동작이 명확하지 않아 혼란을 줄 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;868&quot; data-start=&quot;834&quot;&gt;일부 클라이언트에서 캐싱 등의 문제를 일으킬 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;900&quot; data-start=&quot;870&quot; data-ke-size=&quot;size23&quot;&gt;⚠️ 1.3 요청 본문(Request Body)&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;http&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;복사&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;DELETE /users { &quot;user_ids&quot;: [123, 124, 125] } &lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1104&quot; data-start=&quot;961&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1056&quot; data-start=&quot;961&quot;&gt;&lt;b&gt;공식 HTTP 스펙에 명확히 금지된 것은 아니지만&lt;/b&gt;,&lt;br /&gt;일부 서버나 프록시, 브라우저가 &lt;b&gt;DELETE + Body&lt;/b&gt;를 예상하지 않고 무시할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;1104&quot; data-start=&quot;1057&quot;&gt;하지만 &lt;b&gt;복수 항목을 한 번에 삭제&lt;/b&gt;하는 경우에는 효율적인 방법이기도 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;1109&quot; data-start=&quot;1106&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1133&quot; data-start=&quot;1111&quot; data-ke-size=&quot;size26&quot;&gt;2. 복수 항목 삭제 시 실무 선택&lt;/h2&gt;
&lt;p data-end=&quot;1221&quot; data-start=&quot;1135&quot; data-ke-size=&quot;size16&quot;&gt;제가 작업한 프로젝트에서는 메타 광고의 자동입찰 설정에서 여러 개의 rule(rabmidx)을 한꺼번에 삭제해야 했습니다. 다음과 같은 고민이 있었습니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1349&quot; data-start=&quot;1223&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1262&quot; data-start=&quot;1223&quot;&gt;Path 방식은 &lt;b&gt;1개씩만 삭제 가능&lt;/b&gt;하므로 반복 요청 필요&lt;/li&gt;
&lt;li data-end=&quot;1302&quot; data-start=&quot;1263&quot;&gt;Query 방식은 &lt;b&gt;길어질 수 있고&lt;/b&gt; RESTful하지 않음&lt;/li&gt;
&lt;li data-end=&quot;1349&quot; data-start=&quot;1303&quot;&gt;Body 방식은 &lt;b&gt;삭제할 ID 리스트를 담기에 적합&lt;/b&gt;, 트랜잭션 묶기도 쉬움&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-end=&quot;1376&quot; data-start=&quot;1351&quot; data-ke-size=&quot;size23&quot;&gt;  그래서 최종적으로 선택한 방식은?&lt;/h3&gt;
&lt;div&gt;
&lt;div&gt;http&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;복사&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;DELETE /api/v1/auto-bidding/roas/meta &lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;json&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;복사&lt;span data-state=&quot;closed&quot;&gt;편집&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;&quot;rabmidx_list&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;/span&gt;&lt;span&gt;&lt;span&gt;101&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;102&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;103&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1584&quot; data-start=&quot;1479&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1528&quot; data-start=&quot;1479&quot;&gt;rabmidx_list 라는 배열을 Request Body에 담아 서버에 보냄&lt;/li&gt;
&lt;li data-end=&quot;1548&quot; data-start=&quot;1529&quot;&gt;서버는 이를 반복 처리하여 삭제&lt;/li&gt;
&lt;li data-end=&quot;1584&quot; data-start=&quot;1549&quot;&gt;&lt;b&gt;속도와 일관성&lt;/b&gt;, &lt;b&gt;트랜잭션 처리&lt;/b&gt; 측면에서 효과적&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;1589&quot; data-start=&quot;1586&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1612&quot; data-start=&quot;1591&quot; data-ke-size=&quot;size26&quot;&gt;3. 정리: 어떤 방식이 맞을까?&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;목적방식설명
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;1842&quot; data-start=&quot;1614&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;1842&quot; data-start=&quot;1654&quot;&gt;
&lt;tr data-end=&quot;1703&quot; data-start=&quot;1654&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1665&quot; data-start=&quot;1654&quot;&gt;단일 항목 삭제&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1691&quot; data-start=&quot;1665&quot;&gt;DELETE /resource/{id}&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1703&quot; data-start=&quot;1691&quot;&gt;✅ 가장 권장됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1771&quot; data-start=&quot;1704&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1715&quot; data-start=&quot;1704&quot;&gt;복수 항목 삭제&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1745&quot; data-start=&quot;1715&quot;&gt;DELETE /resource + Body&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1771&quot; data-start=&quot;1745&quot;&gt;⚠️ 실무에서 자주 사용됨 (주의 필요)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1842&quot; data-start=&quot;1772&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1784&quot; data-start=&quot;1772&quot;&gt;조회/필터링 목적&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1815&quot; data-start=&quot;1784&quot;&gt;DELETE /resource?key=value&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1842&quot; data-start=&quot;1815&quot;&gt;❌ 명확하지 않으며 RESTful하지 않음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;1847&quot; data-start=&quot;1844&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1859&quot; data-start=&quot;1849&quot; data-ke-size=&quot;size26&quot;&gt;4. 실무 팁&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2079&quot; data-start=&quot;1861&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1912&quot; data-start=&quot;1861&quot;&gt;내부 API나 통제된 환경에서는 DELETE + Body를 활용해도 큰 문제 없음&lt;/li&gt;
&lt;li data-end=&quot;1961&quot; data-start=&quot;1913&quot;&gt;공개 API라면 DELETE /resource/{id} 형식을 기본으로 구성&lt;/li&gt;
&lt;li data-end=&quot;2024&quot; data-start=&quot;1962&quot;&gt;&lt;b&gt;프론트에서 삭제 실패 복구가 중요할 경우&lt;/b&gt; &amp;rarr; 각각 DELETE /id 요청 보내는 방식이 좋음&lt;/li&gt;
&lt;li data-end=&quot;2079&quot; data-start=&quot;2025&quot;&gt;&lt;b&gt;데이터가 많고 트랜잭션 묶기가 필요한 경우&lt;/b&gt; &amp;rarr; DELETE + Body가 더 효과적&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;2084&quot; data-start=&quot;2081&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2092&quot; data-start=&quot;2086&quot; data-ke-size=&quot;size26&quot;&gt;마무리&lt;/h2&gt;
&lt;p data-end=&quot;2192&quot; data-start=&quot;2094&quot; data-ke-size=&quot;size16&quot;&gt;HTTP 스펙은 하나지만, 현실에서는 다양한 제약과 유즈케이스가 존재합니다. 중요한 건 &lt;b&gt;요청의 의미가 명확하고&lt;/b&gt;, &lt;b&gt;시스템 구조에 잘 맞는 방식&lt;/b&gt;을 선택하는 것입니다.&lt;/p&gt;
&lt;p data-end=&quot;2254&quot; data-start=&quot;2194&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;ldquo;왜 이 방식이 이 기능에 적합한가?&amp;rdquo;&lt;/b&gt; 를 기준으로, 여러분의 API 설계가 더 탄탄해지길 바랍니다!&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/143</guid>
      <comments>https://nicksoon.tistory.com/entry/%E2%9C%85-HTTP-DELETE-%EC%9A%94%EC%B2%AD-%EC%96%B4%EB%96%A4-%EB%B0%A9%EC%8B%9D%EC%9D%B4-%EC%A0%95%EB%8B%B5%EC%9D%BC%EA%B9%8C#entry143comment</comments>
      <pubDate>Fri, 25 Jul 2025 16:12:42 +0900</pubDate>
    </item>
    <item>
      <title> ️ 해킹&amp;middot;보안 주요 용어 정리표</title>
      <link>https://nicksoon.tistory.com/entry/%F0%9F%9B%A1%EF%B8%8F-%ED%95%B4%ED%82%B9%C2%B7%EB%B3%B4%EC%95%88-%EC%A3%BC%EC%9A%94-%EC%9A%A9%EC%96%B4-%EC%A0%95%EB%A6%AC%ED%91%9C</link>
      <description>&lt;h2 data-end=&quot;137&quot; data-start=&quot;115&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #333333; font-size: 16px; letter-spacing: 0px;&quot;&gt;분류용어쉽게 말하면핵심 개념/특징&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;1802&quot; data-start=&quot;139&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;1802&quot; data-start=&quot;218&quot;&gt;
&lt;tr data-end=&quot;282&quot; data-start=&quot;218&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;229&quot; data-start=&quot;218&quot;&gt;  접근 권한&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;248&quot; data-start=&quot;229&quot;&gt;&lt;b&gt;루팅 (Rooting)&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;264&quot; data-start=&quot;248&quot;&gt;스마트폰을 뿌리까지 뚫음&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;282&quot; data-start=&quot;264&quot;&gt;안드로이드 루트 권한 획득&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;346&quot; data-start=&quot;283&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;294&quot; data-start=&quot;283&quot;&gt;  접근 권한&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;314&quot; data-start=&quot;294&quot;&gt;&lt;b&gt;루트킷 (Rootkit)&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;331&quot; data-start=&quot;314&quot;&gt;몰래 루트 권한 탈취 도구&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;346&quot; data-start=&quot;331&quot;&gt;백도어 + 은폐 기능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;417&quot; data-start=&quot;347&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;359&quot; data-start=&quot;347&quot;&gt;  바이러스/웜&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;380&quot; data-start=&quot;359&quot;&gt;&lt;b&gt;스턱스넷 (Stuxnet)&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;396&quot; data-start=&quot;380&quot;&gt;공장 설비 망가뜨리는 웜&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;417&quot; data-start=&quot;396&quot;&gt;핵시설 파괴 목적, PLC 공격&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;490&quot; data-start=&quot;418&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;429&quot; data-start=&quot;418&quot;&gt;  무선 해킹&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;452&quot; data-start=&quot;429&quot;&gt;&lt;b&gt;Evil Twin Attack&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;470&quot; data-start=&quot;452&quot;&gt;가짜 Wi-Fi 만들어 유도&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;490&quot; data-start=&quot;470&quot;&gt;피싱 사이트 유도, 정보 탈취&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;570&quot; data-start=&quot;491&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;502&quot; data-start=&quot;491&quot;&gt;  심리 공격&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;534&quot; data-start=&quot;502&quot;&gt;&lt;b&gt;사회공학 (Social Engineering)&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;551&quot; data-start=&quot;534&quot;&gt;사람을 속여서 정보를 얻음&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;570&quot; data-start=&quot;551&quot;&gt;메일, 전화, 대면 공격 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;635&quot; data-start=&quot;571&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;580&quot; data-start=&quot;571&quot;&gt;  속임수&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;600&quot; data-start=&quot;580&quot;&gt;&lt;b&gt;피싱 (Phishing)&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;617&quot; data-start=&quot;600&quot;&gt;진짜처럼 속여서 정보 탈취&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;635&quot; data-start=&quot;617&quot;&gt;이메일, 가짜 사이트 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;720&quot; data-start=&quot;636&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;645&quot; data-start=&quot;636&quot;&gt;  속임수&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;665&quot; data-start=&quot;645&quot;&gt;&lt;b&gt;파밍 (Pharming)&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;697&quot; data-start=&quot;665&quot;&gt;악성코드로 진짜 주소 눌러도 피싱 사이트로 감염 유도&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;720&quot; data-start=&quot;697&quot;&gt;DNS 변조, Hosts 파일 조작&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;787&quot; data-start=&quot;721&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;733&quot; data-start=&quot;721&quot;&gt;  URL 조작&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;746&quot; data-start=&quot;733&quot;&gt;&lt;b&gt;타이포스쿼팅&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;768&quot; data-start=&quot;746&quot;&gt;주소 오타 노려 가짜 사이트로 유도&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;787&quot; data-start=&quot;768&quot;&gt;네이버 대신 neiver 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;856&quot; data-start=&quot;788&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;800&quot; data-start=&quot;788&quot;&gt;  URL 조작&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;817&quot; data-start=&quot;800&quot;&gt;&lt;b&gt;Tabnabbing&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;839&quot; data-start=&quot;817&quot;&gt;몰래 열린 탭을 피싱 페이지로 바꿈&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;856&quot; data-start=&quot;839&quot;&gt;_blank 링크 취약점&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;923&quot; data-start=&quot;857&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;867&quot; data-start=&quot;857&quot;&gt;  거짓정보&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;883&quot; data-start=&quot;867&quot;&gt;&lt;b&gt;혹스 (Hoax)&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;906&quot; data-start=&quot;883&quot;&gt;&amp;ldquo;이거 바이러스야!&amp;rdquo; 거짓 정보 유포&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;923&quot; data-start=&quot;906&quot;&gt;공포심 유발, 혼란 조장&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;982&quot; data-start=&quot;924&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;935&quot; data-start=&quot;924&quot;&gt;  주소 위조&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;953&quot; data-start=&quot;935&quot;&gt;&lt;b&gt;IP Spoofing&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;965&quot; data-start=&quot;953&quot;&gt;IP 주소를 속임&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;982&quot; data-start=&quot;965&quot;&gt;출처를 위조해 신뢰 유도&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1046&quot; data-start=&quot;983&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;995&quot; data-start=&quot;983&quot;&gt;  트래픽 공격&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1015&quot; data-start=&quot;995&quot;&gt;&lt;b&gt;Port Scanning&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1030&quot; data-start=&quot;1015&quot;&gt;열린 포트 찾는 스캐닝&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1046&quot; data-start=&quot;1030&quot;&gt;보안 취약점 조사 도구&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1123&quot; data-start=&quot;1047&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1059&quot; data-start=&quot;1047&quot;&gt;  트래픽 공격&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1078&quot; data-start=&quot;1059&quot;&gt;&lt;b&gt;Smurf Attack&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1094&quot; data-start=&quot;1078&quot;&gt;ICMP 패킷 폭탄 공격&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1123&quot; data-start=&quot;1094&quot;&gt;Echo 요청 &amp;rarr; Broadcast 응답 폭탄&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1183&quot; data-start=&quot;1124&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1136&quot; data-start=&quot;1124&quot;&gt;  트래픽 공격&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1149&quot; data-start=&quot;1136&quot;&gt;&lt;b&gt;Nuking&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1167&quot; data-start=&quot;1149&quot;&gt;특정 IP에 패킷 연속 전송&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1183&quot; data-start=&quot;1167&quot;&gt;윈도우 블루스크린 유도&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1245&quot; data-start=&quot;1184&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1195&quot; data-start=&quot;1184&quot;&gt;  감시 공격&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1219&quot; data-start=&quot;1195&quot;&gt;&lt;b&gt;패킷 스니핑 (Sniffing)&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1232&quot; data-start=&quot;1219&quot;&gt;몰래 트래픽 엿보기&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1245&quot; data-start=&quot;1232&quot;&gt;도청, 정보 탈취&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1319&quot; data-start=&quot;1246&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1257&quot; data-start=&quot;1246&quot;&gt;  위장 공격&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1278&quot; data-start=&quot;1257&quot;&gt;&lt;b&gt;스푸핑 (Spoofing)&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1306&quot; data-start=&quot;1278&quot;&gt;속이는 것 전부 (IP, DNS, MAC 등)&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1319&quot; data-start=&quot;1306&quot;&gt;속임수 기반 공격&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1390&quot; data-start=&quot;1320&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1333&quot; data-start=&quot;1320&quot;&gt;  제로데이 공격&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1355&quot; data-start=&quot;1333&quot;&gt;&lt;b&gt;Zero-Day Attack&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1376&quot; data-start=&quot;1355&quot;&gt;&lt;b&gt;알려지지 않은&lt;/b&gt; 취약점 이용&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1390&quot; data-start=&quot;1376&quot;&gt;보안 패치 전 공격&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1456&quot; data-start=&quot;1391&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1403&quot; data-start=&quot;1391&quot;&gt;  스위치 공격&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1424&quot; data-start=&quot;1403&quot;&gt;&lt;b&gt;Switch Jamming&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1437&quot; data-start=&quot;1424&quot;&gt;네트워크 혼란 유도&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1456&quot; data-start=&quot;1437&quot;&gt;스위치 MAC 테이블 무력화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1513&quot; data-start=&quot;1457&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1468&quot; data-start=&quot;1457&quot;&gt;  작은 누수&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1481&quot; data-start=&quot;1468&quot;&gt;&lt;b&gt;살라미 기법&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1496&quot; data-start=&quot;1481&quot;&gt;돈을 아주 조금씩 빼감&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1513&quot; data-start=&quot;1496&quot;&gt;로그 변조, 자투리 절취&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1585&quot; data-start=&quot;1514&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1528&quot; data-start=&quot;1514&quot;&gt;  협박형 악성코드&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1552&quot; data-start=&quot;1528&quot;&gt;&lt;b&gt;트랙웨어 (Ransomware)&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1566&quot; data-start=&quot;1552&quot;&gt;파일 잠그고 돈 요구&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1585&quot; data-start=&quot;1566&quot;&gt;몸값 요구, 암호화 후 협박&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1660&quot; data-start=&quot;1586&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1597&quot; data-start=&quot;1586&quot;&gt;  공포 유도&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1621&quot; data-start=&quot;1597&quot;&gt;&lt;b&gt;스케어웨어 (Scareware)&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1640&quot; data-start=&quot;1621&quot;&gt;&amp;ldquo;당신 감염됨!&amp;rdquo; 공포심 조장&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1660&quot; data-start=&quot;1640&quot;&gt;가짜 보안 경고 후 결제 유도&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1733&quot; data-start=&quot;1661&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1672&quot; data-start=&quot;1661&quot;&gt;  광고 공격&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1699&quot; data-start=&quot;1672&quot;&gt;&lt;b&gt;멀버타이징 (Malvertising)&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1717&quot; data-start=&quot;1699&quot;&gt;정상 광고로 위장한 악성코드&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1733&quot; data-start=&quot;1717&quot;&gt;광고 클릭만으로 감염됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1802&quot; data-start=&quot;1734&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1747&quot; data-start=&quot;1734&quot;&gt;  광고 프로그램&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1767&quot; data-start=&quot;1747&quot;&gt;&lt;b&gt;애드웨어 (Adware)&lt;/b&gt;&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1785&quot; data-start=&quot;1767&quot;&gt;광고를 계속 띄우는 프로그램&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1802&quot; data-start=&quot;1785&quot;&gt;사용자의 동의 없이 설치&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;1807&quot; data-start=&quot;1804&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;1824&quot; data-start=&quot;1809&quot; data-ke-size=&quot;size26&quot;&gt;  유형별 정리 요약&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;유형관련 용어
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;2155&quot; data-start=&quot;1826&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;2155&quot; data-start=&quot;1867&quot;&gt;
&lt;tr data-end=&quot;1888&quot; data-start=&quot;1867&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1877&quot; data-start=&quot;1867&quot;&gt;✅ 권한 탈취&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;1888&quot; data-start=&quot;1877&quot;&gt;루팅, 루트킷&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1913&quot; data-start=&quot;1889&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1900&quot; data-start=&quot;1889&quot;&gt;  무선 공격&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;1913&quot; data-start=&quot;1900&quot;&gt;Evil Twin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1960&quot; data-start=&quot;1914&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1926&quot; data-start=&quot;1914&quot;&gt;  심리/속임수&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;1960&quot; data-start=&quot;1926&quot;&gt;피싱, 파밍, 혹스, 타이포스쿼팅, Tabnabbing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2039&quot; data-start=&quot;1961&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1978&quot; data-start=&quot;1961&quot;&gt;  트래픽/네트워크 공격&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;2039&quot; data-start=&quot;1978&quot;&gt;Smurf, Nuking, IP Spoofing, Switch Jamming, Port Scanning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2084&quot; data-start=&quot;2040&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2050&quot; data-start=&quot;2040&quot;&gt;  악성코드&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;2084&quot; data-start=&quot;2050&quot;&gt;스턱스넷, 트랙웨어, 스케어웨어, 멀버타이징, 애드웨어&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2129&quot; data-start=&quot;2085&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2097&quot; data-start=&quot;2085&quot;&gt; ️ 정보 유출&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;2129&quot; data-start=&quot;2097&quot;&gt;Sniffing, Spoofing, Zero-Day&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;2155&quot; data-start=&quot;2130&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;2141&quot; data-start=&quot;2130&quot;&gt;  금융/사기&lt;/td&gt;
&lt;td data-col-size=&quot;md&quot; data-end=&quot;2155&quot; data-start=&quot;2141&quot;&gt;살라미, 스케어웨어&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;2160&quot; data-start=&quot;2157&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;2173&quot; data-start=&quot;2162&quot; data-ke-size=&quot;size26&quot;&gt;✅ 한 줄 요약&lt;/h2&gt;
&lt;blockquote data-end=&quot;2292&quot; data-start=&quot;2175&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;2292&quot; data-start=&quot;2177&quot; data-ke-size=&quot;size16&quot;&gt;정보보안 위협은 크게 &lt;b&gt;속이는 공격 / 강제로 침입하는 공격 / 몰래 빼내는 공격&lt;/b&gt;으로 나눌 수 있고,&lt;br /&gt;각 공격마다 도구나 수법이 다르기 때문에 &lt;b&gt;이름과 개념을 정확히 구분&lt;/b&gt;하는 것이 중요해!&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>학점은행제,자격증/정보처리기사 공부</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/142</guid>
      <comments>https://nicksoon.tistory.com/entry/%F0%9F%9B%A1%EF%B8%8F-%ED%95%B4%ED%82%B9%C2%B7%EB%B3%B4%EC%95%88-%EC%A3%BC%EC%9A%94-%EC%9A%A9%EC%96%B4-%EC%A0%95%EB%A6%AC%ED%91%9C#entry142comment</comments>
      <pubDate>Fri, 25 Jul 2025 09:59:54 +0900</pubDate>
    </item>
    <item>
      <title>Malvertising (멀버타이징)</title>
      <link>https://nicksoon.tistory.com/entry/Malvertising-%EB%A9%80%EB%B2%84%ED%83%80%EC%9D%B4%EC%A7%95</link>
      <description>&lt;h2 data-end=&quot;102&quot; data-start=&quot;91&quot; data-ke-size=&quot;size26&quot;&gt;  단어 분석&lt;/h2&gt;
&lt;blockquote data-end=&quot;148&quot; data-start=&quot;104&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;148&quot; data-start=&quot;106&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Malicious + Advertising = Malvertising&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;221&quot; data-start=&quot;150&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;174&quot; data-start=&quot;150&quot;&gt;&lt;b&gt;Malicious (악의적인)&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;221&quot; data-start=&quot;175&quot;&gt;&lt;b&gt;Advertising (광고)&lt;/b&gt;&lt;br /&gt;  즉, &lt;b&gt;악성 광고&lt;/b&gt;를 의미해!&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;226&quot; data-start=&quot;223&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;242&quot; data-start=&quot;228&quot; data-ke-size=&quot;size26&quot;&gt;  쉽게 설명하면?&lt;/h2&gt;
&lt;blockquote data-end=&quot;308&quot; data-start=&quot;244&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;308&quot; data-start=&quot;246&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;정상적인 광고처럼 보이지만&lt;/b&gt;,&lt;br /&gt;실제로는 &lt;b&gt;클릭하는 순간 악성코드가 몰래 깔리는 공격&lt;/b&gt;이야!  &lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end=&quot;313&quot; data-start=&quot;310&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;330&quot; data-start=&quot;315&quot; data-ke-size=&quot;size26&quot;&gt;  예시로 설명해볼게&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;495&quot; data-start=&quot;332&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;365&quot; data-start=&quot;332&quot;&gt;너가 유명 뉴스 사이트에 들어갔어. (정상 사이트야!)&lt;/li&gt;
&lt;li data-end=&quot;425&quot; data-start=&quot;366&quot;&gt;그런데 그 안에 있던 &lt;b&gt;배너 광고&lt;/b&gt;에&lt;br /&gt;&lt;b&gt;해커가 만든 악성 스크립트&lt;/b&gt;가 숨겨져 있었어.&lt;/li&gt;
&lt;li data-end=&quot;450&quot; data-start=&quot;426&quot;&gt;너는 그냥 광고를 클릭했을 뿐인데...&lt;/li&gt;
&lt;li data-end=&quot;495&quot; data-start=&quot;451&quot;&gt;  &lt;b&gt;랜섬웨어, 스파이웨어&lt;/b&gt; 같은 악성코드가 &lt;b&gt;자동으로 설치됨!&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-end=&quot;500&quot; data-start=&quot;497&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;513&quot; data-start=&quot;502&quot; data-ke-size=&quot;size26&quot;&gt;  특징 요약&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;항목설명
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;736&quot; data-start=&quot;515&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;736&quot; data-start=&quot;543&quot;&gt;
&lt;tr data-end=&quot;575&quot; data-start=&quot;543&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;548&quot; data-start=&quot;543&quot;&gt;정체&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;575&quot; data-start=&quot;548&quot;&gt;Malicious + Advertising&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;614&quot; data-start=&quot;576&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;581&quot; data-start=&quot;576&quot;&gt;방식&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;614&quot; data-start=&quot;581&quot;&gt;&lt;b&gt;정상적인 광고 네트워크를 이용해 악성코드 유포&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;655&quot; data-start=&quot;615&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;623&quot; data-start=&quot;615&quot;&gt;감염 경로&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;655&quot; data-start=&quot;623&quot;&gt;&lt;b&gt;광고 클릭&lt;/b&gt; 또는 광고에 자동 실행 코드 포함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;707&quot; data-start=&quot;656&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;661&quot; data-start=&quot;656&quot;&gt;특징&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;707&quot; data-start=&quot;661&quot;&gt;&lt;b&gt;보안 솔루션 우회 가능&lt;/b&gt;, &lt;b&gt;대형 사이트 방문자도 감염될 수 있음&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;736&quot; data-start=&quot;708&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;712&quot; data-start=&quot;708&quot;&gt;예&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;736&quot; data-start=&quot;712&quot;&gt;뉴스 사이트, 유튜브, 게임 광고 등&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;hr data-end=&quot;741&quot; data-start=&quot;738&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;754&quot; data-start=&quot;743&quot; data-ke-size=&quot;size26&quot;&gt;✅ 한 줄 요약&lt;/h2&gt;
&lt;blockquote data-end=&quot;804&quot; data-start=&quot;756&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;804&quot; data-start=&quot;758&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Malvertising = 광고를 통해 악성코드를 유포하는 최신 해킹 기법!&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>학점은행제,자격증/정보처리기사 공부</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/141</guid>
      <comments>https://nicksoon.tistory.com/entry/Malvertising-%EB%A9%80%EB%B2%84%ED%83%80%EC%9D%B4%EC%A7%95#entry141comment</comments>
      <pubDate>Thu, 24 Jul 2025 14:26:24 +0900</pubDate>
    </item>
    <item>
      <title>switch jamming</title>
      <link>https://nicksoon.tistory.com/entry/switch-jamming</link>
      <description>&lt;h2 data-end=&quot;118&quot; data-start=&quot;95&quot; data-ke-size=&quot;size26&quot;&gt;  먼저, 네트워크 스위치가 뭐야?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;235&quot; data-start=&quot;120&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;169&quot; data-start=&quot;120&quot;&gt;**스위치(Switch)**는 컴퓨터끼리 &lt;b&gt;데이터를 정확하게 전달해주는 장비&lt;/b&gt;야.&lt;/li&gt;
&lt;li data-end=&quot;235&quot; data-start=&quot;170&quot;&gt;예를 들어 A가 B에게 보내는 메시지는,&lt;br /&gt;  스위치가 보고 &amp;ldquo;아~ 이건 B한테 가야지!&amp;rdquo; 하고 딱! 보내줘.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;279&quot; data-start=&quot;237&quot; data-ke-size=&quot;size16&quot;&gt;즉, &lt;b&gt;누가 누구에게 데이터를 주고받는지 기억해서 정리해 주는 장치&lt;/b&gt;야!&lt;/p&gt;
&lt;p data-end=&quot;279&quot; data-start=&quot;237&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;279&quot; data-start=&quot;237&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;311&quot; data-start=&quot;286&quot; data-ke-size=&quot;size26&quot;&gt;  그럼 Switch Jamming은?&lt;/h2&gt;
&lt;blockquote data-end=&quot;401&quot; data-start=&quot;313&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;401&quot; data-start=&quot;315&quot; data-ke-size=&quot;size16&quot;&gt;해커가 &lt;b&gt;스위치의 기억을 혼란스럽게&lt;/b&gt; 만들어서&lt;br /&gt;데이터가 &lt;b&gt;엉뚱한 데로 가게 하거나&lt;/b&gt;,&lt;br /&gt;&lt;b&gt;모든 포트에 다 퍼지게 만드는 공격&lt;/b&gt;이야!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end=&quot;406&quot; data-start=&quot;403&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;422&quot; data-start=&quot;408&quot; data-ke-size=&quot;size26&quot;&gt;  아주 쉬운 예시&lt;/h2&gt;
&lt;p data-end=&quot;429&quot; data-start=&quot;424&quot; data-ke-size=&quot;size16&quot;&gt;상상해봐!&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;486&quot; data-start=&quot;431&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;445&quot; data-start=&quot;431&quot;&gt;스위치는 학교 선생님!&lt;/li&gt;
&lt;li data-end=&quot;486&quot; data-start=&quot;446&quot;&gt;학생 A가 B에게 쪽지를 보내면, 선생님이 &amp;ldquo;B한테만 전달!&amp;rdquo; 해줘.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;500&quot; data-start=&quot;488&quot; data-ke-size=&quot;size16&quot;&gt;근데 누가 계속 말해:&lt;/p&gt;
&lt;blockquote data-end=&quot;544&quot; data-start=&quot;501&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;544&quot; data-start=&quot;503&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;저 A예요!&amp;rdquo;&lt;br /&gt;&amp;ldquo;저도 A예요!&amp;rdquo;&lt;br /&gt;&amp;ldquo;저기요~ 저도 A예요!&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;583&quot; data-start=&quot;546&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 거짓말하는 애들이 너무 많아서&lt;br /&gt;선생님(스위치)이 헷갈려!&lt;/p&gt;
&lt;p data-end=&quot;624&quot; data-start=&quot;585&quot; data-ke-size=&quot;size16&quot;&gt;결국 선생님은 &amp;ldquo;몰라! 그냥 모든 애들한테 쪽지를 줘!&amp;rdquo; 하고 퍼뜨림!&lt;/p&gt;
&lt;p data-end=&quot;650&quot; data-start=&quot;626&quot; data-ke-size=&quot;size16&quot;&gt;➡️ 이게 바로 &lt;b&gt;스위치 재밍&lt;/b&gt;이야  &lt;/p&gt;
&lt;hr data-end=&quot;655&quot; data-start=&quot;652&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;673&quot; data-start=&quot;657&quot; data-ke-size=&quot;size26&quot;&gt;  이 공격의 핵심은?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;864&quot; data-start=&quot;675&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;733&quot; data-start=&quot;675&quot;&gt;스위치는 &lt;b&gt;MAC 주소 테이블&lt;/b&gt;이라는 걸로&lt;br /&gt;&amp;ldquo;이 컴퓨터는 이 포트에 있어~&amp;rdquo; 하고 기억해.&lt;/li&gt;
&lt;li data-end=&quot;800&quot; data-start=&quot;734&quot;&gt;근데 해커가 &lt;b&gt;수백 개의 가짜 MAC 주소&lt;/b&gt;를 막 보내서&lt;br /&gt;  &lt;b&gt;스위치의 기억 공간을 꽉 채워버려!&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;835&quot; data-start=&quot;801&quot;&gt;그러면 스위치는 &lt;b&gt;모든 포트에 브로드캐스트&lt;/b&gt; 하게 돼!&lt;/li&gt;
&lt;li data-end=&quot;864&quot; data-start=&quot;836&quot;&gt;해커는 그걸 &lt;b&gt;몰래 듣는(스니핑)&lt;/b&gt; 데 써!&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end=&quot;869&quot; data-start=&quot;866&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;882&quot; data-start=&quot;871&quot; data-ke-size=&quot;size26&quot;&gt;✅ 한 줄 요약&lt;/h2&gt;
&lt;blockquote data-end=&quot;966&quot; data-start=&quot;884&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;966&quot; data-start=&quot;886&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Switch Jamming = 스위치한테 수많은 가짜 주소를 보내서, 스위치를 헷갈리게 만들고 데이터가 엉뚱하게 흐르게 하는 해킹 공격!&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end=&quot;971&quot; data-start=&quot;968&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-end=&quot;994&quot; data-start=&quot;973&quot; data-ke-size=&quot;size26&quot;&gt;  정보처리기사 실기 요점 정리&lt;/h2&gt;
&lt;div&gt;
&lt;div&gt;항목설명
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-end=&quot;1151&quot; data-start=&quot;996&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody data-end=&quot;1151&quot; data-start=&quot;1024&quot;&gt;
&lt;tr data-end=&quot;1041&quot; data-start=&quot;1024&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1029&quot; data-start=&quot;1024&quot;&gt;대상&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1041&quot; data-start=&quot;1029&quot;&gt;네트워크 스위치&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1066&quot; data-start=&quot;1042&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1047&quot; data-start=&quot;1042&quot;&gt;방법&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1066&quot; data-start=&quot;1047&quot;&gt;가짜 MAC 주소 폭탄 전송&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1107&quot; data-start=&quot;1067&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1072&quot; data-start=&quot;1067&quot;&gt;결과&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1107&quot; data-start=&quot;1072&quot;&gt;스위치 MAC 테이블 마비 &amp;rarr; 데이터가 모든 포트로 퍼짐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr data-end=&quot;1151&quot; data-start=&quot;1108&quot;&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1116&quot; data-start=&quot;1108&quot;&gt;해커 목적&lt;/td&gt;
&lt;td data-col-size=&quot;sm&quot; data-end=&quot;1151&quot; data-start=&quot;1116&quot;&gt;&lt;b&gt;데이터 가로채기(스니핑)&lt;/b&gt;, &lt;b&gt;네트워크 혼란 유도&lt;/b&gt;&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;</description>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/140</guid>
      <comments>https://nicksoon.tistory.com/entry/switch-jamming#entry140comment</comments>
      <pubDate>Thu, 24 Jul 2025 10:18:50 +0900</pubDate>
    </item>
    <item>
      <title>알려지지 않은 취약점 공격이란?</title>
      <link>https://nicksoon.tistory.com/entry/%EC%95%8C%EB%A0%A4%EC%A7%80%EC%A7%80-%EC%95%8A%EC%9D%80-%EC%B7%A8%EC%95%BD%EC%A0%90-%EA%B3%B5%EA%B2%A9%EC%9D%B4%EB%9E%80</link>
      <description>&lt;p data-end=&quot;174&quot; data-start=&quot;121&quot; data-ke-size=&quot;size16&quot;&gt;이건 &lt;b&gt;프로그램이나 앱 안에 몰래 숨어 있는 &amp;lsquo;구멍&lt;/b&gt;&amp;rsquo;을 해커가 먼저 찾아서 공격하는 거야.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;298&quot; data-start=&quot;176&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;216&quot; data-start=&quot;176&quot;&gt;이 구멍은 &lt;b&gt;아무도 아직 모르는&lt;/b&gt; 거야. (심지어 만든 회사도!)&lt;/li&gt;
&lt;li data-end=&quot;251&quot; data-start=&quot;217&quot;&gt;그래서 &lt;b&gt;&quot;제로데이(0-day)&quot; 공격&lt;/b&gt;이라고도 불러.&lt;/li&gt;
&lt;li data-end=&quot;298&quot; data-start=&quot;252&quot;&gt;해커가 이 구멍을 통해 컴퓨터 안에 몰래 들어가거나, 바이러스를 심을 수 있어!&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;309&quot; data-start=&quot;300&quot; data-ke-size=&quot;size16&quot;&gt;  예를 들어:&lt;/p&gt;
&lt;blockquote data-end=&quot;402&quot; data-start=&quot;310&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-end=&quot;402&quot; data-start=&quot;312&quot; data-ke-size=&quot;size16&quot;&gt;너가 게임을 하고 있는데, 누군가가 그 게임에 숨겨진 문을 통해 몰래 들어와서 너 몰래 캐릭터를 조종하는 거야.&lt;br /&gt;그 문은 게임 만든 사람도 아직 모르는 거야!&lt;/p&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;</description>
      <category>학점은행제,자격증/정보처리기사 공부</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/139</guid>
      <comments>https://nicksoon.tistory.com/entry/%EC%95%8C%EB%A0%A4%EC%A7%80%EC%A7%80-%EC%95%8A%EC%9D%80-%EC%B7%A8%EC%95%BD%EC%A0%90-%EA%B3%B5%EA%B2%A9%EC%9D%B4%EB%9E%80#entry139comment</comments>
      <pubDate>Fri, 11 Jul 2025 19:17:12 +0900</pubDate>
    </item>
    <item>
      <title>Evil Twin Attack이란?</title>
      <link>https://nicksoon.tistory.com/entry/Evil-Twin-Attack%EC%9D%B4%EB%9E%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Evil Twin Attack&lt;/b&gt;은 영어로 &quot;악당 쌍둥이 공격&quot;이야. 그런데 이건 진짜 쌍둥이가 아니라, &lt;b&gt;가짜 와이파이를 진짜처럼 흉내내는 속임수&lt;/b&gt;야!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;179&quot; data-start=&quot;163&quot; data-ke-size=&quot;size23&quot;&gt;  예를 들어 볼게:&lt;/h3&gt;
&lt;p data-end=&quot;229&quot; data-start=&quot;181&quot; data-ke-size=&quot;size16&quot;&gt;네가 &lt;b&gt;스타벅스에서 &quot;Starbucks_WiFi&quot;&lt;/b&gt;라는 와이파이를 자주 쓰고 있어.&lt;/p&gt;
&lt;p data-end=&quot;301&quot; data-start=&quot;231&quot; data-ke-size=&quot;size16&quot;&gt;그런데 누가 &lt;b&gt;&quot;Starbucks_Free_WiFi&quot;&lt;/b&gt;라는 이름으로 &lt;b&gt;똑같이 생긴 와이파이&lt;/b&gt;를 만들어서 너한테 보여줘.&lt;/p&gt;
&lt;p data-end=&quot;395&quot; data-start=&quot;303&quot; data-ke-size=&quot;size16&quot;&gt;네가 &amp;ldquo;어? 이게 진짜 스타벅스 와이파이인가?&amp;rdquo; 헷갈려서 &lt;b&gt;잘못 연결하면&lt;/b&gt;,&lt;br /&gt;그 사람이 너의 &lt;b&gt;비밀번호, 사진, 메시지&lt;/b&gt; 같은 걸 몰래 볼 수 있어!  &lt;/p&gt;
&lt;p data-end=&quot;395&quot; data-start=&quot;303&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;426&quot; data-start=&quot;402&quot; data-ke-size=&quot;size23&quot;&gt;  왜 &quot;가짜 WiFi&quot; 공격일까?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;503&quot; data-start=&quot;428&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;458&quot; data-start=&quot;428&quot;&gt;&lt;b&gt;진짜처럼 보이지만 사실은 가짜&lt;/b&gt; 와이파이니까!&lt;/li&gt;
&lt;li data-end=&quot;503&quot; data-start=&quot;459&quot;&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-end=&quot;527&quot; data-start=&quot;510&quot; data-ke-size=&quot;size23&quot;&gt; ️ 어떻게 조심할까?&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;625&quot; data-start=&quot;529&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;558&quot; data-start=&quot;529&quot;&gt;&lt;b&gt;모르는 와이파이는 함부로 연결하지 않기!&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;585&quot; data-start=&quot;559&quot;&gt;&lt;b&gt;비밀번호 없는 와이파이는 조심하기!&lt;/b&gt;&lt;/li&gt;
&lt;li data-end=&quot;625&quot; data-start=&quot;586&quot;&gt;&lt;b&gt;VPN&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;해당 자료는 GPT 한테 물어보며 이해 한 것을 옮겨 적었습니다&lt;/p&gt;</description>
      <category>학점은행제,자격증/정보처리기사 공부</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/138</guid>
      <comments>https://nicksoon.tistory.com/entry/Evil-Twin-Attack%EC%9D%B4%EB%9E%80#entry138comment</comments>
      <pubDate>Fri, 11 Jul 2025 19:15:46 +0900</pubDate>
    </item>
    <item>
      <title>Netlify 프로젝트 배포 후 가비아 서브도메인 연결하기</title>
      <link>https://nicksoon.tistory.com/entry/Netlify-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B0%B0%ED%8F%AC-%ED%9B%84-%EA%B0%80%EB%B9%84%EC%95%84-%EC%84%9C%EB%B8%8C%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;배포를 마치고 Netlify 기본 URL이 아닌, 내가 소유한 도메인 study.nickdeveloper.co.kr로 접속하려면 &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;1460&quot; data-origin-height=&quot;792&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4f6oo/btsOOn0ZAIG/8ug6nKb2oowZvW9P3mpNlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4f6oo/btsOOn0ZAIG/8ug6nKb2oowZvW9P3mpNlk/img.png&quot; data-alt=&quot;배포 후 결과 이미지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4f6oo/btsOOn0ZAIG/8ug6nKb2oowZvW9P3mpNlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4f6oo%2FbtsOOn0ZAIG%2F8ug6nKb2oowZvW9P3mpNlk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1460&quot; height=&quot;792&quot; data-origin-width=&quot;1460&quot; data-origin-height=&quot;792&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;배포 후 결과 이미지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Netlify로 배포만 한 경우, study.nickdeveloper.co.kr이 아닌 https://[랜덤].netlify.app 형식의 기본 URL로만 접속이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포를 하고 도메인을 연결을 하지 않았으면 study.nickdeveloper.co.kr 이 아닌 다른 Netlify에서 제공하는 URL이 나옵니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1618&quot; data-origin-height=&quot;752&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JOFz3/btsOQxU8syS/ZGKmcUvaMqKaeFJinmbKDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JOFz3/btsOQxU8syS/ZGKmcUvaMqKaeFJinmbKDk/img.png&quot; data-alt=&quot;배포 전 URL&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JOFz3/btsOQxU8syS/ZGKmcUvaMqKaeFJinmbKDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJOFz3%2FbtsOQxU8syS%2FZGKmcUvaMqKaeFJinmbKDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1618&quot; height=&quot;752&quot; data-origin-width=&quot;1618&quot; data-origin-height=&quot;752&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;배포 전 URL&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;386&quot; data-start=&quot;348&quot; data-ke-size=&quot;size23&quot;&gt;1️⃣ Netlify에서 Domain Management 클릭&lt;/h3&gt;
&lt;p data-end=&quot;442&quot; data-start=&quot;388&quot; data-ke-size=&quot;size16&quot;&gt;Netlify 프로젝트 대시보드에서 &lt;b&gt;&quot;Domain management&quot;&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;2040&quot; data-origin-height=&quot;1036&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4itSE/btsORarD978/ED3bxZUJp2yUS6O6kHmM3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4itSE/btsORarD978/ED3bxZUJp2yUS6O6kHmM3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4itSE/btsORarD978/ED3bxZUJp2yUS6O6kHmM3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4itSE%2FbtsORarD978%2FED3bxZUJp2yUS6O6kHmM3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;1036&quot; data-origin-width=&quot;2040&quot; data-origin-height=&quot;1036&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;1004&quot; data-origin-height=&quot;582&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q8AH5/btsOOCDwAG7/k8JHS0kl1prqCckjk3cqJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q8AH5/btsOOCDwAG7/k8JHS0kl1prqCckjk3cqJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q8AH5/btsOOCDwAG7/k8JHS0kl1prqCckjk3cqJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq8AH5%2FbtsOOCDwAG7%2Fk8JHS0kl1prqCckjk3cqJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1004&quot; height=&quot;582&quot; data-origin-width=&quot;1004&quot; data-origin-height=&quot;582&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;1330&quot; data-origin-height=&quot;608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/banf7R/btsOOLOa2eP/DXjTdBtzohaod3KHtGIjzk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/banf7R/btsOOLOa2eP/DXjTdBtzohaod3KHtGIjzk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/banf7R/btsOOLOa2eP/DXjTdBtzohaod3KHtGIjzk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbanf7R%2FbtsOOLOa2eP%2FDXjTdBtzohaod3KHtGIjzk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1330&quot; height=&quot;608&quot; data-origin-width=&quot;1330&quot; data-origin-height=&quot;608&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;h3 data-end=&quot;467&quot; data-start=&quot;449&quot; data-ke-size=&quot;size23&quot;&gt;2️⃣ 연결할 도메인 입력&lt;/h3&gt;
&lt;p data-end=&quot;525&quot; data-start=&quot;469&quot; data-ke-size=&quot;size16&quot;&gt;사용할 도메인 또는 서브도메인(예: study.nickdeveloper.co.kr)을 입력합니다.&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;1436&quot; data-origin-height=&quot;1388&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lbYCw/btsOOIRn081/rYEB2p6t5tmwTzRLT8lERk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lbYCw/btsOOIRn081/rYEB2p6t5tmwTzRLT8lERk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lbYCw/btsOOIRn081/rYEB2p6t5tmwTzRLT8lERk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlbYCw%2FbtsOOIRn081%2FrYEB2p6t5tmwTzRLT8lERk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1436&quot; height=&quot;1388&quot; data-origin-width=&quot;1436&quot; data-origin-height=&quot;1388&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;h3 data-end=&quot;570&quot; data-start=&quot;532&quot; data-ke-size=&quot;size23&quot;&gt;3️⃣ 도메인 등록 업체(예: 가비아)에서 DNS 레코드 추가&lt;/h3&gt;
&lt;p data-end=&quot;619&quot; data-start=&quot;572&quot; data-ke-size=&quot;size16&quot;&gt;가비아 등에서 도메인을 구매한 경우, 다음 두 가지 DNS 레코드를 추가해야 합니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;759&quot; data-start=&quot;621&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;683&quot; data-start=&quot;621&quot;&gt;&lt;b&gt;TXT 레코드&lt;/b&gt;&lt;br /&gt;&amp;rarr; Netlify가 도메인 소유를 인증할 수 있도록 TXT 값을 설정합니다.&lt;/li&gt;
&lt;li data-end=&quot;759&quot; data-start=&quot;685&quot;&gt;&lt;b&gt;CNAME 레코드&lt;/b&gt;&lt;br /&gt;&amp;rarr; study(서브도메인) &amp;rarr; your-site.netlify.app 형식으로 연결합니다.&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;2850&quot; data-origin-height=&quot;340&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2es33/btsOO8CmwiE/ECoas730NyVvreizjMFoR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2es33/btsOO8CmwiE/ECoas730NyVvreizjMFoR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2es33/btsOO8CmwiE/ECoas730NyVvreizjMFoR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2es33%2FbtsOO8CmwiE%2FECoas730NyVvreizjMFoR0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2850&quot; height=&quot;340&quot; data-origin-width=&quot;2850&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;TXT 를 추가 합니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2868&quot; data-origin-height=&quot;322&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJk2EM/btsOQ8tPP8o/bCP6p0tOic55SIKYj71Y31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJk2EM/btsOQ8tPP8o/bCP6p0tOic55SIKYj71Y31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJk2EM/btsOQ8tPP8o/bCP6p0tOic55SIKYj71Y31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJk2EM%2FbtsOQ8tPP8o%2FbCP6p0tOic55SIKYj71Y31%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2868&quot; height=&quot;322&quot; data-origin-width=&quot;2868&quot; data-origin-height=&quot;322&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;CNAME 추가를 합니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2898&quot; data-origin-height=&quot;320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MSsqr/btsOPW9dEKL/Qt1F92xV4yurYVzAKM7foK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MSsqr/btsOPW9dEKL/Qt1F92xV4yurYVzAKM7foK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MSsqr/btsOPW9dEKL/Qt1F92xV4yurYVzAKM7foK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMSsqr%2FbtsOPW9dEKL%2FQt1F92xV4yurYVzAKM7foK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2898&quot; height=&quot;320&quot; data-origin-width=&quot;2898&quot; data-origin-height=&quot;320&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-end=&quot;796&quot; data-start=&quot;766&quot; data-ke-size=&quot;size23&quot;&gt;4️⃣ Netlify에서 Subdomain 추가&lt;/h3&gt;
&lt;p data-end=&quot;856&quot; data-start=&quot;798&quot; data-ke-size=&quot;size16&quot;&gt;Netlify로 돌아와서 &lt;b&gt;&amp;ldquo;Add subdomain&amp;rdquo;&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;1290&quot; data-origin-height=&quot;1144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cr0Tmj/btsOP7CHJpx/D8ea5S6qRzx9m9PkRcOarK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cr0Tmj/btsOP7CHJpx/D8ea5S6qRzx9m9PkRcOarK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cr0Tmj/btsOP7CHJpx/D8ea5S6qRzx9m9PkRcOarK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcr0Tmj%2FbtsOP7CHJpx%2FD8ea5S6qRzx9m9PkRcOarK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1290&quot; height=&quot;1144&quot; data-origin-width=&quot;1290&quot; data-origin-height=&quot;1144&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;h3 data-end=&quot;892&quot; data-start=&quot;863&quot; data-ke-size=&quot;size23&quot;&gt;5️⃣ Netlify DNS 활성화 여부 확인&lt;/h3&gt;
&lt;p data-end=&quot;966&quot; data-start=&quot;894&quot; data-ke-size=&quot;size16&quot;&gt;Netlify DNS가 활성화되었는지 확인하세요. 아직 반영되지 않았다면 &lt;b&gt;5분에서 10분 정도 기다린 후&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;2760&quot; data-origin-height=&quot;856&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCxqrl/btsOQyzKSfd/oCnzAg6xclHwPC0AKff7v0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCxqrl/btsOQyzKSfd/oCnzAg6xclHwPC0AKff7v0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCxqrl/btsOQyzKSfd/oCnzAg6xclHwPC0AKff7v0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCxqrl%2FbtsOQyzKSfd%2FoCnzAg6xclHwPC0AKff7v0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2760&quot; height=&quot;856&quot; data-origin-width=&quot;2760&quot; data-origin-height=&quot;856&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안 나온 경우 5분에서 10분 정도 기다리면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;992&quot; data-start=&quot;973&quot; data-ke-size=&quot;size23&quot;&gt;6️⃣ HTTPS 자동 설정&lt;/h3&gt;
&lt;p data-end=&quot;1063&quot; data-start=&quot;994&quot; data-ke-size=&quot;size16&quot;&gt;Netlify는 Let&amp;rsquo;s Encrypt를 통해 &lt;b&gt;HTTPS 인증서를 자동 발급&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;2688&quot; data-origin-height=&quot;948&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t34K2/btsOOmA0mny/sjiag87r32rTZY6mbVztEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t34K2/btsOOmA0mny/sjiag87r32rTZY6mbVztEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t34K2/btsOOmA0mny/sjiag87r32rTZY6mbVztEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft34K2%2FbtsOOmA0mny%2Fsjiag87r32rTZY6mbVztEk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2688&quot; height=&quot;948&quot; data-origin-width=&quot;2688&quot; data-origin-height=&quot;948&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-end=&quot;1105&quot; data-start=&quot;1070&quot; data-ke-size=&quot;size23&quot;&gt;7️⃣ Verify DNS Configuration 클릭&lt;/h3&gt;
&lt;p data-end=&quot;1193&quot; data-start=&quot;1107&quot; data-ke-size=&quot;size16&quot;&gt;&quot;Verify DNS configuration&quot; 버튼을 클릭하여 설정을 검증합니다.&lt;br /&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;2694&quot; data-origin-height=&quot;1298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGDY6o/btsOPYlJ7jh/yfk7Pm2ZKEOCqjxsVjUAuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGDY6o/btsOPYlJ7jh/yfk7Pm2ZKEOCqjxsVjUAuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGDY6o/btsOPYlJ7jh/yfk7Pm2ZKEOCqjxsVjUAuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGDY6o%2FbtsOPYlJ7jh%2Fyfk7Pm2ZKEOCqjxsVjUAuK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2694&quot; height=&quot;1298&quot; data-origin-width=&quot;2694&quot; data-origin-height=&quot;1298&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;1554&quot; data-origin-height=&quot;542&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6QSfM/btsOPvD4ils/cA1umNqjOjbfVBzJyyTwWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6QSfM/btsOPvD4ils/cA1umNqjOjbfVBzJyyTwWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6QSfM/btsOPvD4ils/cA1umNqjOjbfVBzJyyTwWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6QSfM%2FbtsOPvD4ils%2FcA1umNqjOjbfVBzJyyTwWk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1554&quot; height=&quot;542&quot; data-origin-width=&quot;1554&quot; data-origin-height=&quot;542&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;766&quot; data-origin-height=&quot;98&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S8knQ/btsOQ6QkfZ4/8CxHQb978tPF1iJaVad3pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S8knQ/btsOQ6QkfZ4/8CxHQb978tPF1iJaVad3pk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S8knQ/btsOQ6QkfZ4/8CxHQb978tPF1iJaVad3pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS8knQ%2FbtsOQ6QkfZ4%2F8CxHQb978tPF1iJaVad3pk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;98&quot; data-origin-width=&quot;766&quot; data-origin-height=&quot;98&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;h3 data-end=&quot;1211&quot; data-start=&quot;1200&quot; data-ke-size=&quot;size23&quot;&gt;✅ 최종 확인&lt;/h3&gt;
&lt;p data-end=&quot;1275&quot; data-start=&quot;1213&quot; data-ke-size=&quot;size16&quot;&gt;서브도메인(study.nickdeveloper.co.kr)으로 접속하여 사이트가 잘 연결되었는지 확인합니다.&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>DNS설정</category>
      <category>netlify</category>
      <category>가비아도메인</category>
      <category>개발자블로그</category>
      <category>도메인설정</category>
      <category>도메인연결</category>
      <category>서브도메인</category>
      <category>웹사이트배포</category>
      <category>정적사이트</category>
      <category>프론트엔드</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/137</guid>
      <comments>https://nicksoon.tistory.com/entry/Netlify-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%B0%B0%ED%8F%AC-%ED%9B%84-%EA%B0%80%EB%B9%84%EC%95%84-%EC%84%9C%EB%B8%8C%EB%8F%84%EB%A9%94%EC%9D%B8-%EC%97%B0%EA%B2%B0%ED%95%98%EA%B8%B0#entry137comment</comments>
      <pubDate>Wed, 25 Jun 2025 00:50:44 +0900</pubDate>
    </item>
    <item>
      <title>정보처리기사 실기 공부, 직접 만든 쪽지시험 웹앱으로!</title>
      <link>https://nicksoon.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%8B%A4%EA%B8%B0-%EA%B3%B5%EB%B6%80-%EC%A7%81%EC%A0%91-%EB%A7%8C%EB%93%A0-%EC%AA%BD%EC%A7%80%EC%8B%9C%ED%97%98-%EC%9B%B9%EC%95%B1%EC%9C%BC%EB%A1%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;정보처리기사 실기 공부를 하다 보면 암기할 개념이 정말 많죠. 소프트웨어 공학, 디자인 패턴, SDLC, 알고리즘&amp;hellip; 책만 붙잡고 있다 보면 어느새 집중력이 흐려질 때도 많고요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;347&quot; data-start=&quot;249&quot; data-ke-size=&quot;size16&quot;&gt;그래서 저는 &lt;b&gt;GPT와 함께 쪽지시험 웹앱을 직접 만들어&lt;/b&gt; 공부에 활용하고 있어요.&lt;/p&gt;
&lt;p data-end=&quot;347&quot; data-start=&quot;249&quot; data-ke-size=&quot;size16&quot;&gt;직접 문제를 만들고, 웹으로 테스트를 하다 보니 공부도 더 재밌고 오래 기억에 남습니다.&lt;/p&gt;
&lt;p data-end=&quot;347&quot; data-start=&quot;249&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;678&quot; data-start=&quot;659&quot; data-ke-size=&quot;size26&quot;&gt;⚙️ 어떤 기술로 만들었을까?&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;868&quot; data-start=&quot;680&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;725&quot; data-start=&quot;680&quot;&gt;&lt;b&gt;HTML + CSS + JavaScript&lt;/b&gt;로 구성된 정적인 웹앱입니다.&lt;/li&gt;
&lt;li data-end=&quot;766&quot; data-start=&quot;726&quot;&gt;반응형 디자인을 적용하여 &lt;b&gt;모바일에서도 보기 쉽게&lt;/b&gt; 만들었습니다.&lt;/li&gt;
&lt;li data-end=&quot;811&quot; data-start=&quot;767&quot;&gt;문제는 GPT의 도움을 받아 작성했고, 직접 책을 보며 추가하고 다듬었어요.&lt;/li&gt;
&lt;li data-end=&quot;868&quot; data-start=&quot;812&quot;&gt;JavaScript로 문제를 배열에 저장하고, input으로 정답을 받아 정오답을 판별합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-end=&quot;890&quot; data-start=&quot;875&quot; data-ke-size=&quot;size26&quot;&gt;  공부가 되는 이유&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1059&quot; data-start=&quot;892&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;926&quot; data-start=&quot;892&quot;&gt;&lt;b&gt;직접 문제를 만들면서 개념을 정리&lt;/b&gt;하게 됩니다.&lt;/li&gt;
&lt;li data-end=&quot;971&quot; data-start=&quot;927&quot;&gt;단순히 읽는 것이 아니라 &lt;b&gt;능동적으로 상기하며 복습&lt;/b&gt;할 수 있어요.&lt;/li&gt;
&lt;li data-end=&quot;1013&quot; data-start=&quot;972&quot;&gt;언제 어디서든 웹으로 들어가 &lt;b&gt;간편하게 학습&lt;/b&gt;할 수 있습니다.&lt;/li&gt;
&lt;li data-end=&quot;1059&quot; data-start=&quot;1014&quot;&gt;GPT의 도움으로 &lt;b&gt;빠르게 문제를 생성&lt;/b&gt;하고, 중복도 줄일 수 있었어요.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-end=&quot;1084&quot; data-start=&quot;1066&quot; data-ke-size=&quot;size26&quot;&gt;  앞으로 해보고 싶은 것&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1180&quot; data-start=&quot;1086&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1129&quot; data-start=&quot;1086&quot;&gt;문제를 카테고리별로 나누기 (예: 소프트웨어공학, 네트워크, 알고리즘 등)&lt;/li&gt;
&lt;li data-end=&quot;1146&quot; data-start=&quot;1130&quot;&gt;문제 랜덤 출제 기능 추가&lt;/li&gt;
&lt;li data-end=&quot;1158&quot; data-start=&quot;1147&quot;&gt;정답률 기록 기능&lt;/li&gt;
&lt;li data-end=&quot;1180&quot; data-start=&quot;1159&quot;&gt;로그인 없이 간단한 로컬 저장 기능&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-end=&quot;1196&quot; data-start=&quot;1187&quot; data-ke-size=&quot;size26&quot;&gt;  마무리&lt;/h2&gt;
&lt;p data-end=&quot;1350&quot; data-start=&quot;1198&quot; data-ke-size=&quot;size16&quot;&gt;정보처리기사 실기 시험, 쉽지 않지만 포기하지 않으면 반드시 합격할 수 있다고 믿습니다.&lt;br /&gt;저처럼 스스로 문제를 만들거나, 웹 퀴즈를 만들어보는 것도 좋은 공부 방법이 될 수 있어요.&lt;br /&gt;혹시 관심 있는 분들은 아래 링크에서 직접 풀어보시고, 피드백도 언제든 환영입니다!&lt;/p&gt;
&lt;p data-end=&quot;1426&quot; data-start=&quot;1352&quot; data-ke-size=&quot;size16&quot;&gt;  &lt;a href=&quot;https://study.nickdeveloper.co.kr&quot;&gt;https://study.nickdeveloper.co.kr&lt;/a&gt;&lt;/p&gt;
&lt;p data-end=&quot;1463&quot; data-start=&quot;1428&quot; data-ke-size=&quot;size16&quot;&gt;함께 공부하시는 모든 분들, &lt;b&gt;진심으로 응원합니다!&lt;/b&gt;  ✨&lt;/p&gt;
&lt;pre id=&quot;code_1750743234934&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&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;title&amp;gt;정보처리기사 실기 단답형 퀴즈&amp;lt;/title&amp;gt;
  &amp;lt;style&amp;gt;
    *{
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
  body {
    font-family: sans-serif;
    text-align: center;
    margin: 5vh 5vw;
  }

  .card {
    border: 1px solid #ccc;
    border-radius: 10px;
    padding: 20px;
    max-width: 600px;
    margin: auto;
    box-shadow: 0 0 10px #eee;
  }

  input[type=&quot;text&quot;] {
    width: 90%;
    padding: 12px;
    font-size: 1rem;
    margin-top: 10px;
    margin-bottom: 10px;
    box-sizing: border-box;
  }

  button {
    padding: 10px 16px;
    margin: 5px;
    font-size: 1rem;
    cursor: pointer;
  }

  #result {
    margin-top: 15px;
    font-weight: bold;
  }

  /*   모바일 대응: 화면이 600px 이하일 때 스타일 조정 */
  @media screen and (max-width: 600px) {
    body {
      margin: 5vh 2vw;
    }

    .card {
      padding: 10px;
      width: 100%;
      box-shadow: none;
    }

    input[type=&quot;text&quot;] {
      width: 90vw;
      font-size: 1rem;
    }

    button {
      width: 90vw;
      font-size: 1rem;
    }
  }
&amp;lt;/style&amp;gt;
  &amp;lt;link rel=&quot;icon&quot; href=&quot;https://cdn-icons-png.flaticon.com/512/1055/1055684.png&quot; type=&quot;image/png&quot;&amp;gt;
  &amp;lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&amp;gt;
  &amp;lt;meta name=&quot;description&quot; content=&quot;정보처리기사 실기 단답형 퀴즈로, 소프트웨어 공학과 디자인 패턴에 대한 문제를 제공합니다.&quot;&amp;gt;
  &amp;lt;meta name=&quot;keywords&quot; content=&quot;정보처리기사, 실기, 단답형, 퀴즈, 소프트웨어 공학, 디자인 패턴&quot;&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  &amp;lt;div class=&quot;card&quot;&amp;gt;
    &amp;lt;h2&amp;gt;문제&amp;lt;/h2&amp;gt;
    &amp;lt;div id=&quot;question&quot;&amp;gt;문제를 불러오는 중...&amp;lt;/div&amp;gt;

    &amp;lt;input type=&quot;text&quot; id=&quot;userInput&quot; placeholder=&quot;정답을 입력하세요&quot;&amp;gt;
    &amp;lt;div&amp;gt;
      &amp;lt;button onclick=&quot;prevQuestion()&quot;&amp;gt;이전 문제&amp;lt;/button&amp;gt;
      &amp;lt;button onclick=&quot;checkAnswer()&quot;&amp;gt;정답 확인&amp;lt;/button&amp;gt;
      &amp;lt;button onclick=&quot;nextQuestion()&quot;&amp;gt;다음 문제&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;div id=&quot;result&quot;&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;/div&amp;gt;

  &amp;lt;script&amp;gt;
    const quiz = [
      { q: &quot;소프트웨어의 규모를 LOC 기반으로 예측하고, 소프트웨어 유형에 따라 비용을 산정하는 공식을 적용하는 비용을 산정하는 모델은?&quot;, a: &quot;COCOMO&quot; },
      { q: &quot;조직형, O만 라인 이하의 일반 업무용 소프트웨어 개발 프로젝트&quot;, a: &quot;5만 라인 이하&quot; },
      { q: &quot;반분리형 OO만 라인 이하의 운영체제나 DBMS 같은 소프트웨어 개발 프로젝트&quot;, a: &quot;30만 라인 이하&quot; },
      { q: &quot;TCP와 UDP 중 연결지향적인 프로토콜은?&quot;, a: &quot;TCP&quot; },
      { q: &quot;내방형, OO만 라인 이상의 미사일 유도 시스템, 신호기 제어 시스템 같은 대규모 복잡 소프트웨어 개발 프로젝트&quot;, a: &quot;30만 라인 이상&quot; },
      { q: &quot;프로젝트 핵심 관리 대상 3P&quot;, a: &quot;사람, 문제, 프로세스&quot; },
      { q: &quot;신속하고 반복적인 작업을 통해 지속적으로 작동 가능한 소프트웨어를 개발하는 방식&quot;, a: &quot;애자일&quot; },
      { q: &quot;XP 5가지 핵심&quot;, a: &quot;용기, 존중, 의사소통, 피드백, 단순성&quot; },
      { q: &quot;폭포수 모델과 프로토타이핑 모델의 장점을 결합하고, 위험 분석을 추가하여 점진적으로 개발하는 모델&quot;, a: &quot;나선형 모델&quot; },
      { q: &quot;나선형 모델의 순서&quot;, a: &quot;계획 및 요구 분석, 위험 분석, 프로토타입, 고객 평가 및 피드백&quot; },
      { q: &quot;객체의 세부 구현을 숨기고 인터페이스만 제공하여 내부 구현을 보호한다&quot;, a: &quot;캡슐화&quot; },
      { q: &quot;객체 내부의 세부 사항을 외부로부터 숨김으로써 안정성을 높인다&quot;, a: &quot;정보 은닉&quot; },
      { q: &quot;재사용과 확장성을 위해 상위 클래스의 속성과 메서드를 하위 클래스가 상속한다&quot;, a: &quot;상속&quot; },
      { q: &quot;하나의 인터페이스가 다양한 형태의 구현을 가질 수 있어 유연한 프로그래밍이 가능하다&quot;, a: &quot;다형성&quot; },
      { q: &quot;복잡한 현실 세계를 단순화하여 필요한 부분만을 모델링한다&quot;, a: &quot;추상화&quot; },
      { q: &quot;소프트웨어 개발 단계&quot;, a: &quot;계획, 요구사항 분석, 설계, 구현, 테스트, 유지보수&quot; },
      { q: &quot;소프트웨어 공학의 3R&quot;, a: &quot;역공학, 재공학, 재사용&quot; },
      { q: &quot;정렬 알고리즘 중 평균 시간 복잡도가 가장 빠른 알고리즘은?&quot;, a: &quot;퀵 정렬&quot; },
      { q: &quot;시스템 개발 생명주기(SDLC)의 첫 번째 단계는?&quot;, a: &quot;요구사항 분석&quot; },
      { q: &quot;데이터 흐름도(DFD)에서 처리 과정을 나타내는 기호는?&quot;, a: &quot;원&quot; },
      { q: &quot;교착상태 발생 조건 중 자원을 점유한 채 다른 자원을 기다리는 상태는?&quot;, a: &quot;상호 대기&quot; },
      { q: &quot;비대칭키 암호화 방식 중 대표적인 알고리즘은?&quot;, a: &quot;RSA&quot; },
      { q: &quot;객체를 1개만 생성하고 공유하는 디자인 패턴은?&quot;, a: &quot;Singleton&quot; },
      { q: &quot;객체 생성을 서브 클래스에 위임하는 디자인 패턴은?&quot;, a: &quot;Factory Method&quot; },
      { q: &quot;관찰자에게 상태 변경을 통지하는 디자인 패턴은?&quot;, a: &quot;Observer&quot; },
      { q: &quot;행동 알고리즘을 런타임에 교체할 수 있게 하는 디자인 패턴은?&quot;, a: &quot;Strategy&quot; },
      { q: &quot;알고리즘의 틀을 상위 클래스가 정의하고 하위 클래스가 구체화하는 디자인 패턴은?&quot;, a: &quot;Template Method&quot; },
      { q: &quot;관련 객체를 집합으로 생성하는 디자인 패턴은?&quot;, a: &quot;Abstract Factory&quot; },
      { q: &quot;복잡한 객체 생성 절차를 분리하는 디자인 패턴은?&quot;, a: &quot;Builder&quot; },
      { q: &quot;기존 객체를 복제하여 사용하는 디자인 패턴은?&quot;, a: &quot;Prototype&quot; },
      { q: &quot;호환되지 않는 인터페이스를 연결하는 디자인 패턴은?&quot;, a: &quot;Adapter&quot; },
      { q: &quot;트리 구조로 구성 요소를 조합하는 디자인 패턴은?&quot;, a: &quot;Composite&quot; },
      { q: &quot;기존 객체에 기능을 덧붙이는 디자인 패턴은?&quot;, a: &quot;Decorator&quot; },
      { q: &quot;복잡한 서브시스템에 단순한 인터페이스를 제공하는 디자인 패턴은?&quot;, a: &quot;Facade&quot; },
      { q: &quot;객체에 대한 대리자를 제공하는 디자인 패턴은?&quot;, a: &quot;Proxy&quot; },
      { q: &quot;요청을 객체로 캡슐화하는 디자인 패턴은?&quot;, a: &quot;Command&quot; },
      { q: &quot;상태에 따라 동작이 바뀌는 디자인 패턴은?&quot;, a: &quot;State&quot; },
      { q: &quot;GoF 디자인 패턴의 저자 중 한 명으로, G으로 시작하는 이름은?&quot;, a: &quot;Erich Gamma&quot; },
      { q: &quot;GoF 디자인 패턴 공동 저자 중 H로 시작하는 이름은?&quot;, a: &quot;Richard Helm&quot; },
      { q: &quot;GoF 디자인 패턴 공동 저자 중 J로 시작하는 이름은?&quot;, a: &quot;John Vlissides&quot; },
      { q: &quot;GoF 디자인 패턴 공동 저자 중 J가 아닌 이름은?&quot;, a: &quot;Ralph Johnson&quot; },
      { q: &quot;디자인 패턴 책 \&quot;Design Patterns\&quot;을 집필한 4인의 별칭은?&quot;, a: &quot;GoF&quot; },
      { q: &quot;객체 관계도 사각형&quot;, a: &quot;객체&quot; },
      { q: &quot;객체 관계도 마름모&quot;, a: &quot;관계&quot; },
      { q: &quot;객체 관계도 타원&quot;, a: &quot;속성&quot; },
      { q: &quot;객체 관계도 밑줄 타원&quot;, a: &quot;기본키 속성&quot; },
      { q: &quot;객체 관계도 이중 타원&quot;, a: &quot;복합 속성&quot; },
      { q: &quot;객체 관계도 선 링크&quot;, a: &quot;객체와 속성 연결&quot; },

    ];

    let current = 0;

    function showQuestion() {
      document.getElementById(&quot;question&quot;).innerText = quiz[current].q;
      document.getElementById(&quot;userInput&quot;).value = &quot;&quot;;
      document.getElementById(&quot;result&quot;).innerText = &quot;&quot;;
    }

    function checkAnswer() {
      const userAnswer = document.getElementById(&quot;userInput&quot;).value.trim();
      const correctAnswer = quiz[current].a.trim();

      if (normalize(userAnswer) === normalize(correctAnswer)) {
        document.getElementById(&quot;result&quot;).innerHTML = &quot;✅ 정답입니다!&quot;;
      } else {
        document.getElementById(&quot;result&quot;).innerHTML = `❌ 오답입니다. &amp;lt;br&amp;gt;정답: ${correctAnswer}`;
      }
    }

    function normalize(str) {
      return str.replace(/\s+/g, &quot;&quot;).toLowerCase();
    }

    function nextQuestion() {
      current = (current + 1) % quiz.length;
      showQuestion();
    }
   function prevQuestion() {
      current = (current - 1 + quiz.length) % quiz.length;
      showQuestion();
    }
    window.onload = showQuestion;
  &amp;lt;/script&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제발 학격하자!!&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>GPT활용</category>
      <category>HTML</category>
      <category>단답형퀴즈</category>
      <category>정보처리기사</category>
      <category>정보처리기사실기</category>
      <category>쪽지시험</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/136</guid>
      <comments>https://nicksoon.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EC%8B%A4%EA%B8%B0-%EA%B3%B5%EB%B6%80-%EC%A7%81%EC%A0%91-%EB%A7%8C%EB%93%A0-%EC%AA%BD%EC%A7%80%EC%8B%9C%ED%97%98-%EC%9B%B9%EC%95%B1%EC%9C%BC%EB%A1%9C#entry136comment</comments>
      <pubDate>Tue, 24 Jun 2025 14:38:55 +0900</pubDate>
    </item>
    <item>
      <title>재부팅 시 PM2 프로세스 자동 재실행 설정</title>
      <link>https://nicksoon.tistory.com/entry/%EC%9E%AC%EB%B6%80%ED%8C%85-%EC%8B%9C-PM2-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%9E%90%EB%8F%99-%EC%9E%AC%EC%8B%A4%ED%96%89-%EC%84%A4%EC%A0%95</link>
      <description>&lt;h2 data-end=&quot;52&quot; data-start=&quot;42&quot; data-ke-size=&quot;size26&quot;&gt;. 배경&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;324&quot; data-start=&quot;53&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;164&quot; data-start=&quot;53&quot;&gt;&lt;b&gt;사건&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;164&quot; data-start=&quot;66&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;127&quot; data-start=&quot;66&quot;&gt;서버가 예기치 않게 재부팅되면서, PM2로 구동 중이던 Node.js/Python 서비스가 모두 중단됨&lt;/li&gt;
&lt;li data-end=&quot;164&quot; data-start=&quot;130&quot;&gt;고객이 &amp;ldquo;로그인 불가&amp;rdquo;로 문의 &amp;rarr; 재해 복구 절차 점검&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;220&quot; data-start=&quot;165&quot;&gt;&lt;b&gt;원인&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;220&quot; data-start=&quot;178&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;220&quot; data-start=&quot;178&quot;&gt;서버 재부팅 후 PM2가 자동으로 프로세스를 복원하도록 설정되지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-end=&quot;324&quot; data-start=&quot;221&quot;&gt;&lt;b&gt;영향&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;324&quot; data-start=&quot;234&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;263&quot; data-start=&quot;234&quot;&gt;Web/API 서버 다운 &amp;rarr; 고객 서비스 불가&lt;/li&gt;
&lt;li data-end=&quot;324&quot; data-start=&quot;266&quot;&gt;다행히 DB는 자동으로 올라왔으나, 애플리케이션까지 복구되지 않았다면 큰 사고로 이어질 수 있었음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;341&quot; data-start=&quot;331&quot; data-ke-size=&quot;size26&quot;&gt;2. 환경&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;451&quot; data-start=&quot;342&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;358&quot; data-start=&quot;342&quot;&gt;운영체제: Ubuntu&lt;/li&gt;
&lt;li data-end=&quot;376&quot; data-start=&quot;359&quot;&gt;프로세스 매니저: PM2&lt;/li&gt;
&lt;li data-end=&quot;451&quot; data-start=&quot;377&quot;&gt;구동 중인 앱:
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;451&quot; data-start=&quot;392&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;414&quot; data-start=&quot;392&quot;&gt;app.js (Node.js)&lt;/li&gt;
&lt;li data-end=&quot;451&quot; data-start=&quot;417&quot;&gt;main.py (Python / FastAPI 등)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-end=&quot;476&quot; data-start=&quot;458&quot; data-ke-size=&quot;size26&quot;&gt;3. 해결 및 설정 절차&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-end=&quot;1202&quot; data-start=&quot;478&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li data-end=&quot;706&quot; data-start=&quot;478&quot;&gt;&lt;b&gt;PM2로 애플리케이션 실행&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1746752726839&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 예시: Node.js
pm2 start app.js --name web-server

# 예시: Python (FastAPI/Uvicorn)
pm2 start main.py \
  --name api-server \
  --interpreter python3 \
  -- watch false&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 현재 프로세스 목록&amp;middot;상태 저장&lt;/p&gt;
&lt;pre id=&quot;code_1746752741682&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pm2 save&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;804&quot; data-start=&quot;769&quot; data-ke-size=&quot;size16&quot;&gt;PM2가 관리 중인 프로세스와 환경 설정을 디스크에 기록합니다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-end=&quot;804&quot; data-start=&quot;769&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;804&quot; data-start=&quot;769&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 시스템 부팅 시 PM2가 자동 실행되도록 설정&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1746752788936&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pm2 startup&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;919&quot; data-start=&quot;877&quot;&gt;명령 실행 후 출력되는 스크립트를 복사&amp;middot;붙여넣기 해서 한 번 더 실행&lt;/li&gt;
&lt;li data-end=&quot;988&quot; data-start=&quot;923&quot;&gt;부팅 시 /etc/systemd/system/pm2-root.service 등이 생성되어 PM2가 자동 기동됨&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. 설정 확인&lt;/p&gt;
&lt;pre id=&quot;code_1746752816502&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pm2 list      # 재부팅 후에도 프로세스가 online 상태로 복원됐는지 확인&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-end=&quot;1096&quot; data-start=&quot;1080&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. (선택) 강제 복원&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1202&quot; data-start=&quot;1100&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1166&quot; data-start=&quot;1100&quot;&gt;만약 부팅 직후 바로 복원이 안 될 경우:&lt;/li&gt;
&lt;li data-end=&quot;1166&quot; data-start=&quot;1100&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1746752840587&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pm2 resurrect&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pm2 save 직전 상태로 프로세스를 복원합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 설정해 두면, 이후 서버가 재부팅되어도 PM2가 자동으로 다시 기동되어 애플리케이션이 무중단으로 복원됩니다.&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>pm2</category>
      <category>pm2 sav</category>
      <category>pm2 startup</category>
      <category>ubuntu</category>
      <category>개발필기</category>
      <category>무중단배포</category>
      <category>서비스관리</category>
      <category>시스템스타트업</category>
      <category>자동실행</category>
      <category>재부팅복구</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/135</guid>
      <comments>https://nicksoon.tistory.com/entry/%EC%9E%AC%EB%B6%80%ED%8C%85-%EC%8B%9C-PM2-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%9E%90%EB%8F%99-%EC%9E%AC%EC%8B%A4%ED%96%89-%EC%84%A4%EC%A0%95#entry135comment</comments>
      <pubDate>Fri, 9 May 2025 10:11:55 +0900</pubDate>
    </item>
    <item>
      <title>가비아 네입서버 연결 후 카페24 도메인 관리</title>
      <link>https://nicksoon.tistory.com/entry/%EA%B0%80%EB%B9%84%EC%95%84-%EB%84%A4%EC%9E%85%EC%84%9C%EB%B2%84-%EC%97%B0%EA%B2%B0-%ED%9B%84-%EC%B9%B4%ED%8E%9824-%EB%8F%84%EB%A9%94%EC%9D%B8-%EA%B4%80%EB%A6%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;도메인은 가비아, 호스팅은 카페24로 저렵하게 사용하는 경우 도메인 관리에 문제가 발생을 하는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 서버 전문가가 아닌 분들이 이렇게 하며 관리에 문제가 생깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 카페24로 네입서버 설정한 분들의 문제를 해결하고자 준비했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카페24에서 가비아로 로그인 하지 않고 바로 관리 할 수 있는 방법을 정리 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 필요한 경우 ssl 도메인 인증을 할 경우 필요합니다.&lt;/p&gt;
&lt;p data-ke-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;1645&quot; data-origin-height=&quot;288&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzEnOY/btsNljxrpxe/Ru2O2J0KkSt5odKPfaWw91/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzEnOY/btsNljxrpxe/Ru2O2J0KkSt5odKPfaWw91/img.png&quot; data-alt=&quot;가비아 네임서버 설정 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzEnOY/btsNljxrpxe/Ru2O2J0KkSt5odKPfaWw91/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzEnOY%2FbtsNljxrpxe%2FRu2O2J0KkSt5odKPfaWw91%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1645&quot; height=&quot;288&quot; data-origin-width=&quot;1645&quot; data-origin-height=&quot;288&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가비아 네임서버 설정 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저도 잘 몰라 검색해 보니&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ns1.cafe24.com, ns1.cafe24.co.kr, ns2.cafe24.com, ns2.cafe24.co.kr&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;1676&quot; data-origin-height=&quot;177&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDcyYU/btsNljKHksq/6EtJAj2QK9MUlc9IghW261/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDcyYU/btsNljKHksq/6EtJAj2QK9MUlc9IghW261/img.png&quot; data-alt=&quot;가비아 네입서버 입력&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDcyYU/btsNljKHksq/6EtJAj2QK9MUlc9IghW261/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDcyYU%2FbtsNljKHksq%2F6EtJAj2QK9MUlc9IghW261%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1676&quot; height=&quot;177&quot; data-origin-width=&quot;1676&quot; data-origin-height=&quot;177&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가비아 네입서버 입력&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;revenue_unit_wrap&quot;&gt;
  &lt;div class=&quot;revenue_unit_item adsense responsive&quot;&gt;
    &lt;div class=&quot;revenue_unit_info&quot;&gt;반응형&lt;/div&gt;
    &lt;script src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
    &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-host=&quot;ca-host-pub-9691043933427338&quot; data-ad-client=&quot;ca-pub-8542284842011502&quot; data-ad-format=&quot;auto&quot;&gt;&lt;/ins&gt;
    &lt;script&gt;(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&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;다음 카페24 호스팅 센터에 들어옵니다.&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;309&quot; data-origin-height=&quot;659&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3d18m/btsNg9iXzmF/2dU162dKpU93kUJXaNYWYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3d18m/btsNg9iXzmF/2dU162dKpU93kUJXaNYWYK/img.png&quot; data-alt=&quot;카페24 호스팅 left nav&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3d18m/btsNg9iXzmF/2dU162dKpU93kUJXaNYWYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3d18m%2FbtsNg9iXzmF%2F2dU162dKpU93kUJXaNYWYK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;309&quot; height=&quot;659&quot; data-origin-width=&quot;309&quot; data-origin-height=&quot;659&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;카페24 호스팅 left nav&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &quot;DNS 관리&quot;를 클릭합니다.( 추가로 최근 UI가 변경되어 저도 찾았습니다)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1325&quot; data-origin-height=&quot;328&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dwOmzl/btsNk23MRo9/WbtF611rcK0oToxHsnvbK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dwOmzl/btsNk23MRo9/WbtF611rcK0oToxHsnvbK1/img.png&quot; data-alt=&quot;카페24 도메인 리스트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dwOmzl/btsNk23MRo9/WbtF611rcK0oToxHsnvbK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdwOmzl%2FbtsNk23MRo9%2FWbtF611rcK0oToxHsnvbK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1325&quot; height=&quot;328&quot; data-origin-width=&quot;1325&quot; data-origin-height=&quot;328&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;카페24 도메인 리스트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;등록된 도메인 리스트를 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;선택 후 &quot;DNS 관리&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;883&quot; data-origin-height=&quot;534&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/coMlPC/btsNkwEx0xl/ftIKpzc044dtMUZnpiHPv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/coMlPC/btsNkwEx0xl/ftIKpzc044dtMUZnpiHPv0/img.png&quot; data-alt=&quot;카페24 DNS 관리 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/coMlPC/btsNkwEx0xl/ftIKpzc044dtMUZnpiHPv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcoMlPC%2FbtsNkwEx0xl%2FftIKpzc044dtMUZnpiHPv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;883&quot; height=&quot;534&quot; data-origin-width=&quot;883&quot; data-origin-height=&quot;534&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;카페24 DNS 관리 페이지&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;</description>
      <category>개발/개발 필기</category>
      <category>DNS 관리</category>
      <category>가비아</category>
      <category>관리 위치</category>
      <category>네임서버</category>
      <category>도메인 설정</category>
      <category>카페24</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/134</guid>
      <comments>https://nicksoon.tistory.com/entry/%EA%B0%80%EB%B9%84%EC%95%84-%EB%84%A4%EC%9E%85%EC%84%9C%EB%B2%84-%EC%97%B0%EA%B2%B0-%ED%9B%84-%EC%B9%B4%ED%8E%9824-%EB%8F%84%EB%A9%94%EC%9D%B8-%EA%B4%80%EB%A6%AC#entry134comment</comments>
      <pubDate>Mon, 14 Apr 2025 16:29:44 +0900</pubDate>
    </item>
    <item>
      <title>Git Push 오류 해결하기: non-fast-forward와 그 해결책</title>
      <link>https://nicksoon.tistory.com/entry/Git-Push-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0-non-fast-forward%EC%99%80-%EA%B7%B8-%ED%95%B4%EA%B2%B0%EC%B1%85</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1742346853284.jpg&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/E9xwl/btsMNJENyJ5/m3rWKqtMnrMTDetRUQ03Z0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/E9xwl/btsMNJENyJ5/m3rWKqtMnrMTDetRUQ03Z0/img.jpg&quot; data-alt=&quot;git error&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/E9xwl/btsMNJENyJ5/m3rWKqtMnrMTDetRUQ03Z0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FE9xwl%2FbtsMNJENyJ5%2Fm3rWKqtMnrMTDetRUQ03Z0%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;358&quot; height=&quot;358&quot; data-filename=&quot;1742346853284.jpg&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;git error&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;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Git을 사용하다 보면 &lt;/span&gt;git push&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt; 명령어 실행 시 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;! [rejected] main -&amp;gt; main (non-fast-forward)&lt;span style=&quot;background-color: #ffffff; color: #000000; 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;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이는 여러분의 로컬 &lt;/span&gt;main&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt; 브랜치가 원격 저장소의 &lt;/span&gt;main&lt;span style=&quot;background-color: #ffffff; color: #000000; 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;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;즉, 다른 사람이 여러분이 마지막으로 &lt;/span&gt;pull&lt;span style=&quot;background-color: #ffffff; color: #000000; 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;git push -f&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt; (강제 푸시)는 다른 사람의 작업 내용을 덮어쓸 위험이 있으므로 권장하지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1742346380220&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; git push -f origin
 
 ! [rejected]        main -&amp;gt; main (non-fast-forward)
error: failed to push some refs to '깃주소'&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_1742346461431&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;hint: Updates were rejected because the tip of your current branch is behind
hint: 'git pull ...') before pushing again.&lt;/code&gt;&lt;/pre&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;b&gt;해결책 (권장):&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;git pull origin main&lt;/b&gt;: 이 명령어는 원격 main 브랜치의 최신 변경 사항을 가져와 여러분의 로컬 main 브랜치에 병합합니다. 이렇게 하면 로컬 복사본이 최신 상태가 됩니다. 병합 충돌이 발생하면 수동으로 해결해야 합니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;git push origin main&lt;/b&gt;: 성공적으로 pull 한 후, 이 명령어를 사용하여 로컬 변경 사항을 원격 저장소에 푸시합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;revenue_unit_wrap&quot;&gt;
  &lt;div class=&quot;revenue_unit_item adsense responsive&quot;&gt;
    &lt;div class=&quot;revenue_unit_info&quot;&gt;반응형&lt;/div&gt;
    &lt;script src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
    &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-host=&quot;ca-host-pub-9691043933427338&quot; data-ad-client=&quot;ca-pub-8542284842011502&quot; data-ad-format=&quot;auto&quot;&gt;&lt;/ins&gt;
    &lt;script&gt;(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;git pull이 실패하는 경우:&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1742346414428&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;git pull origin main --allow-unrelated-histories&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 pull 받으면 업로드가 가능합니다&lt;/p&gt;
&lt;pre id=&quot;code_1742346518047&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;From ~~~~깃주소
 * branch            main       -&amp;gt; FETCH_HEAD
Merge made by the 'recursive' strategy.
 README.md | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++&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_1742346561135&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;PS D:\07.work\code\healsCheck&amp;gt; git push main
fatal: 'main' does not appear to be a git repository
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
Enumerating objects: 17, done.
Counting objects: 100% (17/17), done.
Compressing objects: 100% (16/16), done.
Writing objects: 100% (16/16), 7.91 KiB | 3.96 MiB/s, done.
Total 16 (delta 1), reused 0 (delta 0), pack-reused 0
To 깃주소
   4240981..7224391  main -&amp;gt; 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;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이 옵션은 브랜치의 히스토리가 완전히 다를 때 (예: 완전히 별개의 히스토리를 가진 브랜치를 병합하는 경우) 필요합니다. &lt;span style=&quot;color: #ee2323;&quot;&gt;하지만 주의해서 사용해야 합니다. 잘못 사용하면 복잡한 히스토리를 만들 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>Error Handling</category>
      <category>git</category>
      <category>git error</category>
      <category>git pull</category>
      <category>git push</category>
      <category>non-fast-forward</category>
      <category>troubleshooting</category>
      <category>Version Control</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/133</guid>
      <comments>https://nicksoon.tistory.com/entry/Git-Push-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0-non-fast-forward%EC%99%80-%EA%B7%B8-%ED%95%B4%EA%B2%B0%EC%B1%85#entry133comment</comments>
      <pubDate>Wed, 19 Mar 2025 10:15:09 +0900</pubDate>
    </item>
    <item>
      <title>Next.js의 useParams 및 useSearchParams 사용법</title>
      <link>https://nicksoon.tistory.com/entry/Nextjs%EC%9D%98-useParams-%EB%B0%8F-useSearchParams-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Next.js의 최신 버전에서 URL 파라미터 및 쿼리 파라미터를 가져오는 방법이 변경되었습니다. &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;React Router&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;와 다르게, Next.js에서는 &lt;/span&gt;next/navigation&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt; 모듈을 통해 URL의 동적 파라미터 및 쿼리 파라미터를 쉽게 가져올 수 있는 훅들을 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;1. 문자열 및 쿼리 파라미터 가져오기&lt;/h2&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;useParams&lt;span&gt;&amp;nbsp;&lt;/span&gt;훅&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;useParams는 현재 경로에서 동적 파라미터를 가져오는 훅입니다. 주로 페이지 라우팅에서 URL의 세그먼트로 전달된 값을 읽을 때 사용됩니다.&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;사용 예시&lt;/h4&gt;
&lt;pre id=&quot;code_1741758680811&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useParams } from 'next/navigation';

export default function Home() {
    const { clientId } = useParams(); // URL에서 clientId 가져오기
    
    // 구현할 로직...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;위 코드에서 clientId는 URL 경로에 정의된 클라이언트 ID를 나타냅니다.&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;useSearchParams&lt;span&gt;&amp;nbsp;&lt;/span&gt;훅&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;useSearchParams는 URL의 쿼리 파라미터를 가져오는 데 사용됩니다. 이 훅은 검색 문자열에 포함된 파라미터를 쉽게 읽고 쿼리 파라미터를 검색할 수 있도록 도와줍니다.&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;사용 예시&lt;/h4&gt;
&lt;pre id=&quot;code_1741758711148&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { useSearchParams } from 'next/navigation';

export default function Home() {
    const searchParams = useSearchParams(); // 쿼리 파라미터 가져오기
    const media = searchParams.get('media'); // 특정 쿼리 파라미터를 가져옴
    
    // 구현할 로직...
}&lt;/code&gt;&lt;/pre&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;위 코드에서 media는 쿼리 문자열 안의 media 파라미터의 값을 나타냅니다.&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. 프로젝트 폴더 구조&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Next.js에서 동적 라우팅을 구현하기 위해서는 폴더 구조를 다음과 같이 설정해야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1741758746382&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;src/
├── app/
│   ├── client/
│   │   ├── [clientId]/       // 클라이언트 ID를 동적으로 처리
│   │   │   ├── workboard/     // 각 클라이언트의 작업 보드
│   │   │   │   └── page.tsx   // 작업 보드 페이지
│   ├── ...
└── ...&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;navigation.d.ts 을 보면 가져오는 방법이 있습니다&lt;/p&gt;
&lt;pre id=&quot;code_1741758471088&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import type { Params } from '../../server/request/params';
import { type AppRouterInstance } from '../../shared/lib/app-router-context.shared-runtime';
import { ReadonlyURLSearchParams } from './navigation.react-server';

/**
 * A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
 * that lets you *read* the current URL's search parameters.
 *
 * Learn more about [`URLSearchParams` on MDN](https://developer.mozilla.org/docs/Web/API/URLSearchParams)
 *
 * @example
 * ```ts
 * &quot;use client&quot;
 * import { useSearchParams } from 'next/navigation'
 *
 * export default function Page() {
 *   const searchParams = useSearchParams()
 *   searchParams.get('foo') // returns 'bar' when ?foo=bar
 *   // ...
 * }
 * ```
 *
 * Read more: [Next.js Docs: `useSearchParams`](https://nextjs.org/docs/app/api-reference/functions/use-search-params)
 */
export declare function useSearchParams(): ReadonlyURLSearchParams;

/**
 * A [Client Component](https://nextjs.org/docs/app/building-your-application/rendering/client-components) hook
 * that lets you read a route's dynamic params filled in by the current URL.
 *
 * @example
 * ```ts
 * &quot;use client&quot;
 * import { useParams } from 'next/navigation'
 *
 * export default function Page() {
 *   // on /dashboard/[team] where pathname is /dashboard/nextjs
 *   const { team } = useParams() // team === &quot;nextjs&quot;
 * }
 * ```
 *
 * Read more: [Next.js Docs: `useParams`](https://nextjs.org/docs/app/api-reference/functions/use-params)
 */
export declare function useParams&amp;lt;T extends Params = Params&amp;gt;(): T;&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. 요약&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 style=&quot;color: #000000;&quot;&gt;&lt;b&gt;훅 사용&lt;/b&gt;:&lt;span&gt;&amp;nbsp;&lt;/span&gt;useParams와&lt;span&gt;&amp;nbsp;&lt;/span&gt;useSearchParams&lt;span&gt;&amp;nbsp;&lt;/span&gt;훅을 통해 URL의 경로에서 동적 파라미터와 쿼리 파라미터를 가져올 수 있습니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;폴더 구조&lt;/b&gt;: 동적 URL 처리를 위한 폴더 구조를 정의하여 각 클라이언트에 대한 페이지를 쉽게 관리할 수 있습니다.&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;</description>
      <category>개발/개발 필기</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/132</guid>
      <comments>https://nicksoon.tistory.com/entry/Nextjs%EC%9D%98-useParams-%EB%B0%8F-useSearchParams-%EC%82%AC%EC%9A%A9%EB%B2%95#entry132comment</comments>
      <pubDate>Wed, 12 Mar 2025 14:53:18 +0900</pubDate>
    </item>
    <item>
      <title>웹 페이지 캐시 문제 해결하기</title>
      <link>https://nicksoon.tistory.com/entry/%EC%9B%B9-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%BA%90%EC%8B%9C-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</link>
      <description>&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;&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;&lt;/p&gt;
&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;특히, 프론트엔드 작업 후 내 PC에서는 정상적으로 작동하나, &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;고객의 PC에서는 이전 버전이 보이는 상황이 발생할 수 있습니다. &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;그럴 때마다 고객에게 강력 새로고침(CTRL + SHIFT + R)을 &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;&lt;/p&gt;
&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;&lt;b&gt;브라우저 캐시&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt; 때문입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; 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;&lt;span style=&quot;background-color: #ffffff; color: #000000; 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;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;해결책: 캐시 무효화(Cache Busting) 기법&lt;/h4&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;캐시 무효화(Cache Busting)&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; 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;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이는 자바스크립트 파일이나 스타일시트와 같은 리소스 파일의 URL에 &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;&lt;/p&gt;
&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;&lt;/p&gt;
&lt;div class=&quot;revenue_unit_wrap&quot;&gt;
  &lt;div class=&quot;revenue_unit_item adsense responsive&quot;&gt;
    &lt;div class=&quot;revenue_unit_info&quot;&gt;반응형&lt;/div&gt;
    &lt;script src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
    &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-host=&quot;ca-host-pub-9691043933427338&quot; data-ad-client=&quot;ca-pub-8542284842011502&quot; data-ad-format=&quot;auto&quot;&gt;&lt;/ins&gt;
    &lt;script&gt;(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p 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;리소스 파일의 URL에 쿼리 파라미터를 추가하여 버전을 명시합니다. 예를 들어:&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 style=&quot;color: #000000;&quot;&gt;script.js?v=0.1.1&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;style.css?cc=20250306&lt;/li&gt;
&lt;/ul&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;&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;&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;예시&lt;/h4&gt;
&lt;pre id=&quot;code_1741240627165&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import { downloadCSV, formatNumber } from &quot;../function.js?v=0.2.0&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;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;위 방법을 통해, 트래픽 과다 발생을 피하면서도 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;변경된 스크립트가 모든 사용자에게 적시에 반영되도록 할 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;웹 서비스의 안정성과 사용자 경험 개선을 위해 캐시 무효화 기법을 적극 활용하시기 바랍니다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>고객경험</category>
      <category>브라우저캐시</category>
      <category>웹개발</category>
      <category>웹사이트성능</category>
      <category>자동강력새로고침</category>
      <category>캐시 문제</category>
      <category>캐시무효화</category>
      <category>프론트엔드</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/131</guid>
      <comments>https://nicksoon.tistory.com/entry/%EC%9B%B9-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%BA%90%EC%8B%9C-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0#entry131comment</comments>
      <pubDate>Thu, 6 Mar 2025 14:58:41 +0900</pubDate>
    </item>
    <item>
      <title>함수형 프로그래밍의 장점과 실전 활용</title>
      <link>https://nicksoon.tistory.com/entry/%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98-%EC%9E%A5%EC%A0%90%EA%B3%BC-%EC%8B%A4%EC%A0%84-%ED%99%9C%EC%9A%A9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;함수형 함수형 하는데 너무 어렵더라고요&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분명 중요하고 아는 내용인데 개발을 하면서 많이 놓지고 있는 부분이었서요&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;하지만 최근에 저는 함수형 프로그래밍에 대한 이해를 높이고,(배우고~)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;JavaScript에서 그것을 활용하여 코드를 개선하는 데 주력했습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;오늘은 제가 느낀 점과 함께, 함수형 프로그래밍이 어떻게 복잡한 코드를 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; 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&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;아직 100% 이해를 하고 적립한 것이 아닌&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;아~~ 정도 60% 이해를 한 상황이라 설명이 많이 미숙합니다&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;단도직입적으로&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; 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;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;제가 처음 접했던 코드는 다음과 같은 형태로, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;길고 복잡해서 유지보수하기 어려운 부분이 많았습니다:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1740734429732&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;for (let i = start; i &amp;lt; end; i++) {
    const element = KEYWORD_ARRAY[i];
    if (!element) {
        break;
    }
    if (element.relKeyword === keyword) {
        KEYWORD_ARRAY[i].category1 = keyword_info.category ? keyword_info.category.category1 : &quot;&quot;;
        KEYWORD_ARRAY[i].category2 = keyword_info.category ? keyword_info.category.category2 : &quot;&quot;;
        KEYWORD_ARRAY[i].category3 = keyword_info.category ? keyword_info.category.category3 : &quot;&quot;;
        KEYWORD_ARRAY[i].category4 = keyword_info.category ? keyword_info.category.category4 : &quot;&quot;;
        KEYWORD_ARRAY[i].total = keyword_info.total;
    }
}

BASE_KEYWORD_ARRAY.forEach((element, index) =&amp;gt; {
    if (!element) return;
    if (element.relKeyword === keyword) {
        BASE_KEYWORD_ARRAY[index].category1 = keyword_info.category ? keyword_info.category.category1 : &quot;&quot;;
        BASE_KEYWORD_ARRAY[index].category2 = keyword_info.category ? keyword_info.category.category2 : &quot;&quot;;
        BASE_KEYWORD_ARRAY[index].category3 = keyword_info.category ? keyword_info.category.category3 : &quot;&quot;;
        BASE_KEYWORD_ARRAY[index].category4 = keyword_info.category ? keyword_info.category.category4 : &quot;&quot;;
        BASE_KEYWORD_ARRAY[index].total = keyword_info.total;
    }
});&lt;/code&gt;&lt;/pre&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;&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;함수형 접근의 장점&lt;/h2&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;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;다음과 같이 코드를 리팩토링할 수 있었습니다:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1740734553027&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export function* map(iterable, mapFunction) {
    let index = 0;
    for (const item of iterable) {
        yield mapFunction(item,index++);
    }
}

// Generator function that filters elements of an iterable based on a filter function
export function* filter(iterable, filterFunction) {
    for (const item of iterable) {
        if (filterFunction(item)) {
            yield item;
        }
    }
}
export function* sort(iterable, compareFunction) {
    const sortedArray = Array.from(iterable).sort(compareFunction);
    for (const item of sortedArray) {
        yield item;
    }
}

export function* slice(iterable, start, end) {
    let index = 0;
    for (const item of iterable) {
        if (index &amp;gt;= start &amp;amp;&amp;amp; index &amp;lt; end) {
            yield item;
        }
        index++;
        if (index &amp;gt;= end) {
            break;
        }
    }
}

export function* reverse(iterable) {
    const items = Array.from(iterable);
    for (let i = items.length - 1; i &amp;gt;= 0; i--) {
        yield items[i];
    }
}
export function* batch(iterable, size) {
    let batch = [];
    for (const item of iterable) {
        batch.push(item);
        if (batch.length === size) {
            yield batch;
            batch = [];
        }
    }
    if (batch.length &amp;gt; 0) {
        yield batch;
    }
}&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_1740734583561&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export class Processor {
    constructor(iterable) {
        this.iterable = iterable;
    }

    map(mapFunction) {
        this.iterable = map(this.iterable, mapFunction);
        return this;
    }

    filter(filterFunction) {
        this.iterable = filter(this.iterable, filterFunction);
        return this;
    }

    sort(compareFunction) {
        this.iterable = sort(this.iterable, compareFunction);
        return this;
    }
    slice(start, end) {
        this.iterable = slice(this.iterable, start, end);
        return this;
    }

    reverse() {
        this.iterable = reverse(this.iterable);
        return this;
    }
    batch(size) {
        this.iterable = batch(this.iterable, size);
        return this;
    }
    toArray() {
        return Array.from(this.iterable);
    }
}&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_1740734617695&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 키워드 정보를 업데이트하는 함수
function updateKeywordInfo(array, keyword, keywordInfo) {
    return array.map(element =&amp;gt; {
        if (element &amp;amp;&amp;amp; element.relKeyword === keyword) {
            return {
                ...element,
                category1: keywordInfo.category ? keywordInfo.category.category1 : &quot;&quot;,
                category2: keywordInfo.category ? keywordInfo.category.category2 : &quot;&quot;,
                category3: keywordInfo.category ? keywordInfo.category.category3 : &quot;&quot;,
                category4: keywordInfo.category ? keywordInfo.category.category4 : &quot;&quot;,
                total: keywordInfo.total,
            };
        }
        return element; // 업데이트가 필요 없는 경우 원래 요소 반환
    });
 });&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_1740734628793&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 사용하는 방법
const updatedArray = updateKeywordInfo(KEYWORD_ARRAY, keyword, keyword_info);
const updatedBaseArray = updateKeywordInfo(BASE_KEYWORD_ARRAY, keyword, keyword_info);&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;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이로 인해 코드가 훨씬 더 읽기 쉽게 되었고, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; 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;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;느낀 점&lt;/h2&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;응용할 때도 미숙한 점이 많았지만,&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;React와 TypeScript로 관련된 내용을 들었을 때,&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;일반 JavaScript에서 사용할 수 있을지 걱정했지만, 직접 만들어보니 생각보다 쉽고 편했습니다.&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;/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;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&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;코드의 가독성과 재사용성을 높이는 강력한 도구입니다.&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;앞으로도 계속해서 함수형 프로그래밍을 활용하여 보다 나은 코드를 작성해 나가고자 합니다.&lt;/p&gt;
&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;PS 분명 더 짧다고 했는데? 라고 생각을 하시지만 함수형을 만드는 부분을 적은 것이다 보니 더 길게 보이겠지만&amp;nbsp;&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;&lt;/p&gt;</description>
      <category>개발/JavaScript</category>
      <category>Javascript</category>
      <category>가독성</category>
      <category>개발자</category>
      <category>소프트웨어개발</category>
      <category>자바스크립트팁</category>
      <category>재사용성</category>
      <category>코드리팩토링</category>
      <category>코딩</category>
      <category>프로그래밍</category>
      <category>함수형프로그래밍</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/130</guid>
      <comments>https://nicksoon.tistory.com/entry/%ED%95%A8%EC%88%98%ED%98%95-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D%EC%9D%98-%EC%9E%A5%EC%A0%90%EA%B3%BC-%EC%8B%A4%EC%A0%84-%ED%99%9C%EC%9A%A9#entry130comment</comments>
      <pubDate>Fri, 28 Feb 2025 18:27:44 +0900</pubDate>
    </item>
    <item>
      <title>CSS 최적화: clean-css 사용법</title>
      <link>https://nicksoon.tistory.com/entry/CSS-%EC%B5%9C%EC%A0%81%ED%99%94-clean-css-%EC%82%AC%EC%9A%A9%EB%B2%95</link>
      <description>&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;CSS 작업을 하다 보면 파일이 10만 줄이 넘어가는 경우도 발생합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이때 긴 줄이나 주석이 그대로 남아 있으면 Lighthouse에서 경고가 발생할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;CSS 파일의 용량이 크면 다운로드 속도에도 문제가 생길 수 있어 최적화가 필요합니다.&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;clean-css 추천&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 문제를 해결하기 위해 &lt;b&gt;clean-css&lt;/b&gt;를 사용해 CSS 파일을 간편하게 최적화할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 기능은 HTML과 CSS만 사용하는 분들에게는 필요할 수 있지만,&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;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;clean-css 설치&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;먼저, clean-css를 글로벌로 설치합니다:&lt;/p&gt;
&lt;pre id=&quot;code_1740561587974&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install clean-css-cli -g&lt;/code&gt;&lt;/pre&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;CSS 파일 최적화&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그 다음, 원하는 경로에서 CSS 파일을 최소화(minify)할 수 있습니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1740561613784&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cleancss -o dist/styles.min.css src/styles.css&lt;/code&gt;&lt;/pre&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;src/styles.css&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt; 파일을 압축하여 &lt;/span&gt;dist/styles.min.css&lt;span style=&quot;background-color: #ffffff; color: #000000; 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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bn3Veb/btsMwrEiGZN/ZwYsaQKDmdJ8AJYvLPMKqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bn3Veb/btsMwrEiGZN/ZwYsaQKDmdJ8AJYvLPMKqK/img.png&quot; data-alt=&quot;예제 .min.css&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bn3Veb/btsMwrEiGZN/ZwYsaQKDmdJ8AJYvLPMKqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbn3Veb%2FbtsMwrEiGZN%2FZwYsaQKDmdJ8AJYvLPMKqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;822&quot; height=&quot;412&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;412&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;예제 .min.css&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 바뀝니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;자동화 설정&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;단, clean-css는 파일이 자동으로 최적화되지 않으므로 주의가 필요합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이를 위해 nodemon을 이용하여 파일 변경 시 자동으로 명령을 실행하도록 설정할 수 있습니다.&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;nodemon 설치&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1740562399801&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npm install nodemon --save-dev&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;nodemon 구성&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;: &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;프로젝트의 루트 디렉토리에 &lt;/span&gt;nodemon.json&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;을 생성하고 아래와 같이 설정합니다:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1740562435087&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
  &quot;watch&quot;: [&quot;src&quot;],
  &quot;ext&quot;: &quot;css&quot;,
  &quot;exec&quot;: &quot;cleancss -o dist/styles.min.css src/styles.css&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;&lt;b&gt;nodemon 실행&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1740562451455&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npx nodemon&lt;/code&gt;&lt;/pre&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;이렇게 설정하면, src 디렉토리 내의 CSS 파일이 변경될 때마다 clean-css가 실행되어 자동으로 CSS 파일이 최적화됩니다.&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;마무리&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 CSS 최적화에 대해 설명드렸습니다. clean-css와 nodemon을 활용하면 긴 CSS 파일도 손쉽게 관리할 수 있습니다. 성능을 고려한 CSS 작업에 도움이 되길 바랍니다.&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>cleancss</category>
      <category>CSS</category>
      <category>css 최적화</category>
      <category>min.css</category>
      <category>nodemon</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/129</guid>
      <comments>https://nicksoon.tistory.com/entry/CSS-%EC%B5%9C%EC%A0%81%ED%99%94-clean-css-%EC%82%AC%EC%9A%A9%EB%B2%95#entry129comment</comments>
      <pubDate>Wed, 26 Feb 2025 18:34:47 +0900</pubDate>
    </item>
    <item>
      <title>[javascript] 배열 복사 시 주의사항</title>
      <link>https://nicksoon.tistory.com/entry/javascript-%EB%B0%B0%EC%97%B4-%EB%B3%B5%EC%82%AC-%EC%8B%9C-%EC%A3%BC%EC%9D%98%EC%82%AC%ED%95%AD</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;배열을 복사할 때, 특히 이중 배열(Not Nested Array)에서 &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;&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;&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1차원 배열 복사&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아래의 예시처럼 1차원 배열을 복사할 때는 다음과 같은 방법이 일반적입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1739413892670&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const keywordArray = [&quot;가습기&quot;, &quot;사무실용&quot;, &quot;콜드브루앰플&quot;];

// 간단한 복사
let copyKeywordArray = [...keywordArray];&lt;/code&gt;&lt;/pre&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;keywordArray&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;copyKeywordArray&lt;span style=&quot;background-color: #ffffff; color: #000000; 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;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;이중 배열 복사 문제점&lt;/h3&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;간단히 복사하면 원본 데이터를 공유하게 됩니다. 예를 들어:&lt;/p&gt;
&lt;pre id=&quot;code_1739413475416&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const keywordArray = [
    [&quot;가습기&quot;, &quot;사무실용&quot;, &quot;콜드브루앰플&quot;, &quot;사무실용&quot;, &quot;미니가습기&quot;, &quot;유아용가습기&quot;],
    [&quot;가습기&quot;, &quot;사무실용&quot;, &quot;콜드브루앰플&quot;, &quot;사무실용&quot;, &quot;사무실가습기&quot;, &quot;유아용가습기&quot;],
    [&quot;가습기&quot;, &quot;장갑&quot;, &quot;연말선물추천&quot;, &quot;장갑&quot;, &quot;가습기&quot;, &quot;유아용가습기&quot;],
    [&quot;가습기&quot;, &quot;장갑&quot;, &quot;연말선물추천&quot;, &quot;장갑&quot;, &quot;소형가습기&quot;, &quot;유아용가습기&quot;],
    [&quot;가습기&quot;, &quot;미니가습기&quot;, &quot;사무실용&quot;, &quot;설날선물&quot;, &quot;출산선물&quot;, &quot;유아용가습기&quot;],
    [&quot;가습기&quot;, &quot;미니가습기&quot;, &quot;사무실용&quot;, &quot;미니가습기&quot;, &quot;사무실가습기&quot;, &quot;유아용가습기&quot;],
]

// 이렇게 복사하면 문제가 발생합니다
let copyKeywordArray = [...keywordArray];&lt;/code&gt;&lt;/pre&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;copyKeywordArray&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;의 내부 배열을 변경하면 &lt;/span&gt;keywordArray&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&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;709&quot; data-origin-height=&quot;305&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsKzv2/btsMhtOl9rK/qPNPQCm1aZrI6ZzDIK5pQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsKzv2/btsMhtOl9rK/qPNPQCm1aZrI6ZzDIK5pQK/img.png&quot; data-alt=&quot;배열 실습 이미지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsKzv2/btsMhtOl9rK/qPNPQCm1aZrI6ZzDIK5pQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsKzv2%2FbtsMhtOl9rK%2FqPNPQCm1aZrI6ZzDIK5pQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;709&quot; height=&quot;305&quot; data-origin-width=&quot;709&quot; data-origin-height=&quot;305&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;배열 실습 이미지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;올바른 이중 배열 복사 방법&lt;/h3&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;pre id=&quot;code_1739413727721&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let copyKeywordArray = [];
for (let i = 0; i &amp;lt; keywordArray.length; i++) {
    copyKeywordArray[i] = [...keywordArray[i]];
}&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;819&quot; data-origin-height=&quot;377&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dudrjK/btsMgH0QChG/K8lY4AkYJXghKR9SFt6p81/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dudrjK/btsMgH0QChG/K8lY4AkYJXghKR9SFt6p81/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dudrjK/btsMgH0QChG/K8lY4AkYJXghKR9SFt6p81/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdudrjK%2FbtsMgH0QChG%2FK8lY4AkYJXghKR9SFt6p81%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;819&quot; height=&quot;377&quot; data-origin-width=&quot;819&quot; data-origin-height=&quot;377&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;&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>Javascript</category>
      <category>javascript 배열</category>
      <category>js 배열</category>
      <category>배열복사</category>
      <category>웹개발</category>
      <category>이중배열</category>
      <category>프론트엔드</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/128</guid>
      <comments>https://nicksoon.tistory.com/entry/javascript-%EB%B0%B0%EC%97%B4-%EB%B3%B5%EC%82%AC-%EC%8B%9C-%EC%A3%BC%EC%9D%98%EC%82%AC%ED%95%AD#entry128comment</comments>
      <pubDate>Thu, 13 Feb 2025 11:34:38 +0900</pubDate>
    </item>
    <item>
      <title>자주 발생하는 CSV 다운로드 한글 깨짐 현상 해결 방법</title>
      <link>https://nicksoon.tistory.com/entry/%EC%9E%90%EC%A3%BC-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-CSV-%EB%8B%A4%EC%9A%B4%EB%A1%9C%EB%93%9C-%ED%95%9C%EA%B8%80-%EA%B9%A8%EC%A7%90-%ED%98%84%EC%83%81-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;웹에서 CSV 파일을 생성하여 다운로드할 때 한글이 깨지는 문제는 흔히 발생하는 현상입니다.&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: #ee2323;&quot;&gt; &quot;?앺솢怨듭옉???ㅻ궡嫄댁&amp;ldquo; ?명긽?몄젣 ?≪껜?몄젣 ?쇰컲 ?쒕읆 寃몄슜 3L 2媛??명긽?몄젣&quot; &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;&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;&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;이는 CSV 파일의 인코딩 설정과 관련된 문제이며, &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;&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문제 발생 상황:&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;웹 애플리케이션에서 JavaScript를 사용하여 CSV 데이터를 생성하고,&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Blob 객체와 URL.createObjectURL을 이용하여 다운로드 기능을 구현하는 경우,&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다운로드 받은 CSV 파일을 엑셀이나 숫자와 같은 스프레드시트 프로그램으로 열었을 때&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 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;618&quot; data-origin-height=&quot;558&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PiZ5Y/btsMd7ziUGZ/vrOongxLxm5WESg9drHw11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PiZ5Y/btsMd7ziUGZ/vrOongxLxm5WESg9drHw11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PiZ5Y/btsMd7ziUGZ/vrOongxLxm5WESg9drHw11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPiZ5Y%2FbtsMd7ziUGZ%2FvrOongxLxm5WESg9drHw11%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;618&quot; height=&quot;558&quot; data-origin-width=&quot;618&quot; data-origin-height=&quot;558&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;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;504&quot; data-origin-height=&quot;448&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/F9xRO/btsMe4hkVYY/EoMEl1nvDKhOZLVORL8OK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/F9xRO/btsMe4hkVYY/EoMEl1nvDKhOZLVORL8OK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/F9xRO/btsMe4hkVYY/EoMEl1nvDKhOZLVORL8OK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FF9xRO%2FbtsMe4hkVYY%2FEoMEl1nvDKhOZLVORL8OK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;504&quot; height=&quot;448&quot; data-origin-width=&quot;504&quot; data-origin-height=&quot;448&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;div class=&quot;revenue_unit_wrap&quot;&gt;
  &lt;div class=&quot;revenue_unit_item adsense responsive&quot;&gt;
    &lt;div class=&quot;revenue_unit_info&quot;&gt;반응형&lt;/div&gt;
    &lt;script src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
    &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-host=&quot;ca-host-pub-9691043933427338&quot; data-ad-client=&quot;ca-pub-8542284842011502&quot; data-ad-format=&quot;auto&quot;&gt;&lt;/ins&gt;
    &lt;script&gt;(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문제의 원인:&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 문제는 CSV 파일의 인코딩 설정과 관련이 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;일반적으로 엑셀이나 스프레드시트 프로그램은 UTF-8 인코딩을 지원하지만,&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;BOM(Byte Order Mark)이 없는 UTF-8 파일을 제대로 인식하지 못하는 경우가 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;BOM은 파일의 시작 부분에 추가되는 특수 문자로, 파일의 인코딩 방식을 명시하는 역할을 합니다.&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 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;해결 방법:&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;문제를 해결하는 가장 간단한 방법은 CSV 문자열의 앞에 BOM 문자를 추가하는 것입니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;BOM 문자는 Unicode 코드 포인트 \ufeff로 표현됩니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Blob 객체를 생성할 때 CSV 문자열 앞에 \ufeff를 추가하면 엑셀과 같은 스프레드시트 프로그램에서도&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;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;기존 코드:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1739265405705&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const blob = new Blob([csvString], { type: 'text/csv;charset=utf-8;' });
const csvUrl = window.URL.createObjectURL(blob);&lt;/code&gt;&lt;/pre&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1739265424358&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const blob = new Blob([&quot;\ufeff&quot; + csvContent], { type: 'text/csv;charset=utf-8;' });
const url = URL.createObjectURL(blob);&lt;/code&gt;&lt;/pre&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;단순히 csvString 앞에 &quot;\ufeff&quot;를 추가하는 것만으로 한글 깨짐 현상을 해결할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 수정된 코드를 사용하면 생성되는 CSV 파일은 BOM이 포함된 UTF-8 인코딩으로 생성되어&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;다운로드 후 파일을 메모장으로 열어볼 필요가 없어졌습니다.&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 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;결론:&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;CSV 파일 다운로드 시 한글 깨짐 현상은 BOM을 추가하는 간단한 코드 수정으로 해결할 수 있습니다.&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;앞으로 CSV 파일을 생성하여 다운로드하는 기능을 구현할 때는 이 방법을 적용하여&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;</description>
      <category>개발/개발 필기</category>
      <category>CSV</category>
      <category>csv bom</category>
      <category>csv 다운로드</category>
      <category>csv 다운로드 오류</category>
      <category>csv 인코딩</category>
      <category>csv 한글 깨짐</category>
      <category>Javascript</category>
      <category>ufeff</category>
      <category>UTF-8</category>
      <category>한글 깨짐</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/127</guid>
      <comments>https://nicksoon.tistory.com/entry/%EC%9E%90%EC%A3%BC-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-CSV-%EB%8B%A4%EC%9A%B4%EB%A1%9C%EB%93%9C-%ED%95%9C%EA%B8%80-%EA%B9%A8%EC%A7%90-%ED%98%84%EC%83%81-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95#entry127comment</comments>
      <pubDate>Tue, 11 Feb 2025 18:22:56 +0900</pubDate>
    </item>
    <item>
      <title>[Window] docker image 생성이 안되는 경우</title>
      <link>https://nicksoon.tistory.com/entry/Window-docker-image-%EC%83%9D%EC%84%B1%EC%9D%B4-%EC%95%88%EB%90%98%EB%8A%94-%EA%B2%BD%EC%9A%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 윈도우에서 실행이 안되는 경우&lt;/p&gt;
&lt;pre id=&quot;code_1739155063617&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$ docker build -t &amp;lt;&amp;lt; your_image_name &amp;gt;&amp;gt; .
ERROR: error during connect: Head &quot;http://%2F%2F.%2Fpipe%2FdockerDesktopLinuxEngine/_ping&quot;: open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified.&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;1. Docker Desktop 실행 여부&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Windows 권한 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. Docker 환경 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요약을 하면 이렇게 있습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저의 경우 Docker Desktop을 실행하지 않아 무제가 생겼습니다&lt;/p&gt;
&lt;div class=&quot;revenue_unit_wrap&quot;&gt;
  &lt;div class=&quot;revenue_unit_item adsense responsive&quot;&gt;
    &lt;div class=&quot;revenue_unit_info&quot;&gt;반응형&lt;/div&gt;
    &lt;script src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
    &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-host=&quot;ca-host-pub-9691043933427338&quot; data-ad-client=&quot;ca-pub-8542284842011502&quot; data-ad-format=&quot;auto&quot;&gt;&lt;/ins&gt;
    &lt;script&gt;(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&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;793&quot; data-origin-height=&quot;693&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUGVXI/btsMczazuKu/Qoa14lV4GweqK0EiXEGj9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUGVXI/btsMczazuKu/Qoa14lV4GweqK0EiXEGj9K/img.png&quot; data-alt=&quot;윈도우 도커 검색&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUGVXI/btsMczazuKu/Qoa14lV4GweqK0EiXEGj9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUGVXI%2FbtsMczazuKu%2FQoa14lV4GweqK0EiXEGj9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;693&quot; data-origin-width=&quot;793&quot; data-origin-height=&quot;693&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;윈도우 도커 검색&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행을 해주면 정상적으로 이미지를 생성하는 것을 볼 수 있습니다.&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>docker derror</category>
      <category>docker desktop</category>
      <category>docker desktop 실행</category>
      <category>docker image 생성</category>
      <category>docker image 생성 오류</category>
      <category>docker window 실행</category>
      <category>error: error during connect</category>
      <category>the system cannot find the file specified</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/126</guid>
      <comments>https://nicksoon.tistory.com/entry/Window-docker-image-%EC%83%9D%EC%84%B1%EC%9D%B4-%EC%95%88%EB%90%98%EB%8A%94-%EA%B2%BD%EC%9A%B0#entry126comment</comments>
      <pubDate>Mon, 10 Feb 2025 11:43:20 +0900</pubDate>
    </item>
    <item>
      <title>Docker로 애플리케이션 실행하기</title>
      <link>https://nicksoon.tistory.com/entry/Docker%EB%A1%9C-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0</link>
      <description>&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;468&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bn5gDG/btsMaxjNFJY/zkHMKMlTzwb3jhhpakq5nK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bn5gDG/btsMaxjNFJY/zkHMKMlTzwb3jhhpakq5nK/img.png&quot; data-alt=&quot;도커 아이콘&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bn5gDG/btsMaxjNFJY/zkHMKMlTzwb3jhhpakq5nK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbn5gDG%2FbtsMaxjNFJY%2FzkHMKMlTzwb3jhhpakq5nK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;403&quot; height=&quot;332&quot; data-origin-width=&quot;568&quot; data-origin-height=&quot;468&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;도커 아이콘&lt;/figcaption&gt;
&lt;/figure&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;br /&gt;이 글에서는 GitLab에서 애플리케이션 소스를 클론하고 Docker 이미지를 빌드하여 실행하는 방법을 안내합니다.&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;1. Git Bash 실행 및 폴더 이동&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;783&quot; data-origin-height=&quot;647&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/O0X0R/btsL9c2bJSt/OPkrTko7I0kkLPpf2WJGhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/O0X0R/btsL9c2bJSt/OPkrTko7I0kkLPpf2WJGhk/img.png&quot; data-alt=&quot;Git Bash 실행&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/O0X0R/btsL9c2bJSt/OPkrTko7I0kkLPpf2WJGhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FO0X0R%2FbtsL9c2bJSt%2FOPkrTko7I0kkLPpf2WJGhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;470&quot; height=&quot;388&quot; data-origin-width=&quot;783&quot; data-origin-height=&quot;647&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Git Bash 실행&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;먼저 Git Bash를 실행합니다. 원하는 작업 디렉토리로 이동합니다:&lt;/p&gt;
&lt;div style=&quot;background-color: #000000; color: #000000; text-align: start;&quot;&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #000000;&quot;&gt;&lt;code&gt;cd &amp;lt;&amp;lt;폴더 경로&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2. GitLab에서 프로그램 클론&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;GitLab에 있는 프로젝트를 클론합니다:&lt;/p&gt;
&lt;div style=&quot;background-color: #000000; color: #000000; text-align: start;&quot;&gt;
&lt;pre class=&quot;css&quot; style=&quot;color: #000000;&quot;&gt;&lt;code&gt;git clone git@gitlab.~~/username/repository.git
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;3. Dockerfile 확인&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;클론한 디렉토리에 Dockerfile이 있는지 확인합니다. 있는 경우, 아래 명령어로 도커 이미지를 빌드합니다:&lt;/p&gt;
&lt;div style=&quot;background-color: #000000; color: #000000; text-align: start;&quot;&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;color: #000000;&quot;&gt;&lt;code&gt;docker build -t &amp;lt;&amp;lt;your_image_name&amp;gt;&amp;gt; .
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;blockquote style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;div class=&quot;revenue_unit_wrap&quot;&gt;
  &lt;div class=&quot;revenue_unit_item adsense responsive&quot;&gt;
    &lt;div class=&quot;revenue_unit_info&quot;&gt;반응형&lt;/div&gt;
    &lt;script src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
    &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-host=&quot;ca-host-pub-9691043933427338&quot; data-ad-client=&quot;ca-pub-8542284842011502&quot; data-ad-format=&quot;auto&quot;&gt;&lt;/ins&gt;
    &lt;script&gt;(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;color: #000000;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;(참고: 마지막의 .은 현재 디렉토리를 의미합니다.)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;4. Docker 이미지 실행&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;Dockerfile에서 노출된 포트를 확인합니다. 예를 들어, EXPOSE 80으로 설정되어 있는 경우 아래 명령으로 실행합니다:&lt;/p&gt;
&lt;div style=&quot;background-color: #000000; color: #000000; text-align: start;&quot;&gt;
&lt;pre class=&quot;dockerfile&quot; style=&quot;color: #000000;&quot;&gt;&lt;code&gt;docker run -d -p host_port:container_port your_image_name
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;예시로, 8000 포트에서 실행하고 싶다면:&lt;/p&gt;
&lt;div style=&quot;background-color: #000000; color: #000000; text-align: start;&quot;&gt;
&lt;pre class=&quot;pgsql&quot; style=&quot;color: #000000;&quot;&gt;&lt;code&gt;docker run -d -p 8000:80 &amp;lt;&amp;lt;your_image_name&amp;gt;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;5. 실행 확인&lt;/h2&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;div style=&quot;background-color: #000000; color: #000000; text-align: start;&quot;&gt;
&lt;pre class=&quot;javascript&quot; style=&quot;color: #000000;&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;# 실행 확인
docker ps

# 로그 확인
docker logs &amp;lt;컨테이너_ID&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rdddX/btsL92Lj0y1/KF46UmltCl56wgekGLUUh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rdddX/btsL92Lj0y1/KF46UmltCl56wgekGLUUh1/img.png&quot; data-alt=&quot;도커 로그 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rdddX/btsL92Lj0y1/KF46UmltCl56wgekGLUUh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrdddX%2FbtsL92Lj0y1%2FKF46UmltCl56wgekGLUUh1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1295&quot; height=&quot;302&quot; data-origin-width=&quot;1295&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;도커 로그 확인&lt;/figcaption&gt;
&lt;/figure&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;이 과정을 통해 Docker를 사용하여 애플리케이션을 쉽게 실행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>깃 도커</category>
      <category>도커 실행</category>
      <category>도커 실행 노트</category>
      <category>도커 컨테이너</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/125</guid>
      <comments>https://nicksoon.tistory.com/entry/Docker%EB%A1%9C-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0#entry125comment</comments>
      <pubDate>Fri, 7 Feb 2025 13:47:40 +0900</pubDate>
    </item>
    <item>
      <title>네이버 데이터 크롤링 중 429 Too Many Requests 에러 해결하기: API 키 활용 전략</title>
      <link>https://nicksoon.tistory.com/entry/%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%81%AC%EB%A1%A4%EB%A7%81-%EC%A4%91-429-Too-Many-Requests-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0-API-%ED%82%A4-%ED%99%9C%EC%9A%A9-%EC%A0%84%EB%9E%B5</link>
      <description>&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;네이버 데이터를 수집하여 분석하는 과정에서 흔히 마주치는 문제가 바로 &quot;429 Too Many Requests&quot; 에러입니다. 이는 네이버 서버가 과도한 요청을 감지하여 차단하는 보호 메커니즘으로, 단순히 요청 텀을 늘리는 것만으로는 해결되지 않을 수 있습니다. 특히 순차적으로 요청을 보내더라도 에러가 발생하는 경우,&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;여러 개의 네이버 API 키를 순환 사용하는 방법&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;왜 429 에러가 발생할까요?&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;하지만 순차적인 요청에도 에러가 발생할 수 있는데, 이는 네이버 서버의 부하, IP 차단, 또는 다른 제한 사항 때문일 수 있습니다.&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;여러 개의 API 키를 사용하는 전략&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;이 문제를 해결하기 위해, 여러 개의 네이버 API 키를 준비하고, 요청 시마다 키를 순환하면서 사용하는 것이 효과적입니다. 각 API 키는 서로 다른 요청 제한을 가지고 있을 수 있고, 하나의 키가 제한에 걸리더라도 다른 키를 사용하여 요청을 계속 진행할 수 있습니다. 이는 네이버 서버에 대한 부하를 분산시키고, 429 에러를 회피하는 데 도움이 됩니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;284&quot; data-origin-height=&quot;511&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c68ezk/btsL9N0gdwG/EdtiZlNA8C0ZUoXvm0d510/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c68ezk/btsL9N0gdwG/EdtiZlNA8C0ZUoXvm0d510/img.png&quot; data-alt=&quot;내 애플리케이션&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c68ezk/btsL9N0gdwG/EdtiZlNA8C0ZUoXvm0d510/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc68ezk%2FbtsL9N0gdwG%2FEdtiZlNA8C0ZUoXvm0d510%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;284&quot; height=&quot;511&quot; data-origin-width=&quot;284&quot; data-origin-height=&quot;511&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;내 애플리케이션&lt;/figcaption&gt;
&lt;/figure&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;예시 코드 (JavaScript)&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;아래는 JavaScript를 이용하여 여러 개의 네이버 API 키를 순환하며 사용하는 예시 코드입니다. naverApiArray 배열에 여러 개의 API 키 객체를 저장하고, i % naverApiArray.length 를 이용하여 순환합니다. 만약 naverApiArray가 비어있다면 에러 처리를 추가하는 것이 중요합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1738808301042&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const naverApiArray = [
    {
        name: &quot;iksoon1&quot;,
        id: &quot;YOUR_API_ID_1&quot;, // 실제 API ID 입력
        secret: &quot;YOUR_API_SECRET_1&quot;, // 실제 API SECRET 입력
    },
    {
        name: &quot;iksoon2&quot;,
        id: &quot;YOUR_API_ID_2&quot;, // 실제 API ID 입력
        secret: &quot;YOUR_API_SECRET_2&quot;, // 실제 API SECRET 입력
    },
    // ... 더 많은 API 키 추가
];

for (let i = 0; i &amp;lt; 12; i++) {
    if (naverApiArray.length &amp;gt; 0) {
        const naverApi = naverApiArray[i % naverApiArray.length];
        const clientId = naverApi.id;
        const clientSecret = naverApi.secret;

        // 네이버 API 요청 코드 (clientId, clientSecret 사용)
        // ... 네이버 API를 호출하는 부분 ...

    } else {
        console.error(&quot;naverApiArray is empty.  No API keys available.&quot;);
        // 에러 처리 (예: 루프 종료 또는 대체 동작)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중요 고려 사항:&lt;/b&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 style=&quot;color: #000000;&quot;&gt;&lt;b&gt;API 사용 약관 준수:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;네이버 API 사용 약관을 꼼꼼히 확인하고 준수해야 합니다. 특히, 과도한 요청, 불법적인 크롤링, 네이버 서비스에 해를 끼치는 행위는 절대 해서는 안 됩니다.&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;에러 처리:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;API 요청 중 발생할 수 있는 다양한 에러 (네트워크 에러, API 응답 에러 등)에 대한 처리 로직을 추가하여 안정성을 높여야 합니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;지연 시간:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;각 요청 사이에 적절한 지연 시간을 추가하여 서버 부하를 줄이는 것이 좋습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;setTimeout&lt;span&gt;&amp;nbsp;&lt;/span&gt;함수나 비동기 처리를 활용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 전략을 통해 네이버 데이터 크롤링 시 발생하는 429 에러를 효과적으로 예방하고, 안정적으로 데이터를 수집할 수 있습니다. &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;하지만 API 키를 남용하거나 약관을 위반하지 않도록 주의해야 합니다.&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;</description>
      <category>개발/개발 필기</category>
      <category>429 too many requests</category>
      <category>네이버 429</category>
      <category>네이버 429 too many requests 해결</category>
      <category>네이버 api 에러</category>
      <category>네이버 검색 api 에러</category>
      <category>네이버 에러</category>
      <category>에러코드 429</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/124</guid>
      <comments>https://nicksoon.tistory.com/entry/%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%81%AC%EB%A1%A4%EB%A7%81-%EC%A4%91-429-Too-Many-Requests-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0-API-%ED%82%A4-%ED%99%9C%EC%9A%A9-%EC%A0%84%EB%9E%B5#entry124comment</comments>
      <pubDate>Thu, 6 Feb 2025 11:24:40 +0900</pubDate>
    </item>
    <item>
      <title>우분투에서 node.js 설치하기 - 설치 에러</title>
      <link>https://nicksoon.tistory.com/entry/%EC%9A%B0%EB%B6%84%ED%88%AC%EC%97%90%EC%84%9C-nodejs-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0-%EC%84%A4%EC%B9%98-%EC%97%90%EB%9F%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Ubuntu에 Node.js를 설치하는 방법&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로 설치하면서 docker를 사용하는 것이 더 좋았고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;docker의 경우너무 쉽기 때문에 전에 사용한 다른 방법을 공유 드립니다.&lt;/p&gt;
&lt;p data-ke-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 공식 홈페이지 다운로드를 가면 다 있으니 가서 직접 보는 것을 추천 드립니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. &lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;시스템 패키지를 업데이트&lt;/span&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1738804568008&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo apt update
sudo apt upgrade&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;2 Node.js 설치&lt;/h4&gt;
&lt;pre id=&quot;code_1738804831170&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 18버전
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs

# 20버전
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs&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;curl이 없다면&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1738805247592&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apt install curl&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;539&quot; data-origin-height=&quot;175&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Nb3FI/btsL9ahirpQ/zm43Fwe2OKHEoywvuRWiFk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Nb3FI/btsL9ahirpQ/zm43Fwe2OKHEoywvuRWiFk/img.png&quot; data-alt=&quot;node 설치 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Nb3FI/btsL9ahirpQ/zm43Fwe2OKHEoywvuRWiFk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNb3FI%2FbtsL9ahirpQ%2Fzm43Fwe2OKHEoywvuRWiFk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;175&quot; data-origin-width=&quot;539&quot; data-origin-height=&quot;175&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;node 설치 확인&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;npm이 없다고 하네요&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. npm 설치 or yarn 설치&lt;/h4&gt;
&lt;pre id=&quot;code_1738804998814&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;apt install npm&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;만약 설치가 안된다면 NVM&lt;/p&gt;
&lt;pre id=&quot;code_1738805767673&quot; class=&quot;routeros&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;sudo apt remove nodejs&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_1738805883026&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# nvm을 설치해 줍니다
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash&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;만약 nvm이 설치가 안된 경우&lt;/p&gt;
&lt;pre id=&quot;code_1738806122299&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export NVM_DIR=&quot;$HOME/.nvm&quot;
[ -s &quot;$NVM_DIR/nvm.sh&quot; ] &amp;amp;&amp;amp; \. &quot;$NVM_DIR/nvm.sh&quot;

# 또는

export NVM_DIR=&quot;$HOME/.nvm&quot;
[ -s &quot;$NVM_DIR/nvm.sh&quot; ] &amp;amp;&amp;amp; \. &quot;$NVM_DIR/nvm.sh&quot;  # This loads nvm
[ -s &quot;$NVM_DIR/bash_completion&quot; ] &amp;amp;&amp;amp; \. &quot;$NVM_DIR/bash_completion&quot;&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_1738805930822&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 노드 20 버전을 설치합니다
nvm install 20&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_1738806275037&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# Yarn 다운로드 및 설치:
corepack enable yarn&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_1738806206507&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;node -v
npm -v&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;805&quot; data-origin-height=&quot;460&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qTsx2/btsL89Qf9mj/hvsIqcJZU9gTDmFF7XVsP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qTsx2/btsL89Qf9mj/hvsIqcJZU9gTDmFF7XVsP1/img.png&quot; data-alt=&quot;설치 결과 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qTsx2/btsL89Qf9mj/hvsIqcJZU9gTDmFF7XVsP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqTsx2%2FbtsL89Qf9mj%2FhvsIqcJZU9gTDmFF7XVsP1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;805&quot; height=&quot;460&quot; data-origin-width=&quot;805&quot; data-origin-height=&quot;460&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;설치 결과 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;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;a href=&quot;https://nodejs.org/ko/download&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://nodejs.org/ko/download&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738806494885&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;Node.js &amp;mdash; Node.js&amp;reg; 다운로드&quot; data-og-description=&quot;Node.js&amp;reg; is a JavaScript runtime built on Chrome's V8 JavaScript engine.&quot; data-og-host=&quot;nodejs.org&quot; data-og-source-url=&quot;https://nodejs.org/ko/download&quot; data-og-url=&quot;https://nodejs.org/ko/download&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/4lzFV/hyX7ZirDYx/l5yMiPx6uYqXVTRrXnnyRk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/r8r5O/hyX7V8deTg/XJdKRNFR4CMReMrqHKMUn0/img.png?width=224&amp;amp;height=256&amp;amp;face=0_0_224_256&quot;&gt;&lt;a href=&quot;https://nodejs.org/ko/download&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://nodejs.org/ko/download&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/4lzFV/hyX7ZirDYx/l5yMiPx6uYqXVTRrXnnyRk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600,https://scrap.kakaocdn.net/dn/r8r5O/hyX7V8deTg/XJdKRNFR4CMReMrqHKMUn0/img.png?width=224&amp;amp;height=256&amp;amp;face=0_0_224_256');&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;Node.js &amp;mdash; Node.js&amp;reg; 다운로드&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Node.js&amp;reg; is a JavaScript runtime built on Chrome's V8 JavaScript engine.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;nodejs.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;672&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/diBK0s/btsL8lw8nR0/TpkyV7KgDE3uqVsZxk55S1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/diBK0s/btsL8lw8nR0/TpkyV7KgDE3uqVsZxk55S1/img.png&quot; data-alt=&quot;노드 다운로드 공식 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/diBK0s/btsL8lw8nR0/TpkyV7KgDE3uqVsZxk55S1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdiBK0s%2FbtsL8lw8nR0%2FTpkyV7KgDE3uqVsZxk55S1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;846&quot; height=&quot;672&quot; data-origin-width=&quot;846&quot; data-origin-height=&quot;672&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;노드 다운로드 공식 페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1, 원하는 버전, 설치할 PC , 방식, 패키지를 선택해 주세요&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;173&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b6t08Q/btsL9csGd7I/OkDKDEdgI7mpW3cDaJFEOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b6t08Q/btsL9csGd7I/OkDKDEdgI7mpW3cDaJFEOk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b6t08Q/btsL9csGd7I/OkDKDEdgI7mpW3cDaJFEOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb6t08Q%2FbtsL9csGd7I%2FOkDKDEdgI7mpW3cDaJFEOk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;173&quot; data-origin-width=&quot;843&quot; data-origin-height=&quot;173&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;821&quot; data-origin-height=&quot;553&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpFuPs/btsL8Ilhj39/m8n61zjTvmqhhjMU3I76n1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpFuPs/btsL8Ilhj39/m8n61zjTvmqhhjMU3I76n1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpFuPs/btsL8Ilhj39/m8n61zjTvmqhhjMU3I76n1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpFuPs%2FbtsL8Ilhj39%2Fm8n61zjTvmqhhjMU3I76n1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;821&quot; height=&quot;553&quot; data-origin-width=&quot;821&quot; data-origin-height=&quot;553&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;단 nvm 설치가 안되는 경우는&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;nvm으로 직접 이동하는&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1738806674855&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;export NVM_DIR=&quot;$HOME/.nvm&quot;
[ -s &quot;$NVM_DIR/nvm.sh&quot; ] &amp;amp;&amp;amp; \. &quot;$NVM_DIR/nvm.sh&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드를 추가해 주세요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>node js install ubuntu</category>
      <category>node js 설치</category>
      <category>node 다운로드</category>
      <category>node 설치</category>
      <category>node 설치 에러</category>
      <category>node.js 설치</category>
      <category>nodejs install ubuntu</category>
      <category>nodejs 설치</category>
      <category>NVM</category>
      <category>nvm 설치 에러</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/123</guid>
      <comments>https://nicksoon.tistory.com/entry/%EC%9A%B0%EB%B6%84%ED%88%AC%EC%97%90%EC%84%9C-nodejs-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0-%EC%84%A4%EC%B9%98-%EC%97%90%EB%9F%AC#entry123comment</comments>
      <pubDate>Thu, 6 Feb 2025 10:54:48 +0900</pubDate>
    </item>
    <item>
      <title>Docker Program Error and Solution - When Ubuntu Docker Deployment Fails</title>
      <link>https://nicksoon.tistory.com/entry/Docker-Program-Error-and-Solution-When-Ubuntu-Docker-Deployment-Fails</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Recently, an urgent error occurred in the program, and after making modifications for deployment, &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;we encountered a problem where downloading did not happen when trying to run it on Docker. &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;Here, I will share the cause of the issue and the steps taken to resolve it.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Cause of the Issue&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Server-Docker Relationship Check:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;There may have been issues related to the IP block between the server and Docker or port issues.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;Incorrect configuration might also be a possibility.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Code Version Check:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;It was identified that the code was not updated to the latest version.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Duplicate Execution Check:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;Two instances of the same program were running on the same server.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Below is my server structure. I marked it simply&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;1030&quot; data-origin-height=&quot;614&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6mYcR/btsL7cUhaXL/DKnuvlr0Lfn07ezHp1jYZk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6mYcR/btsL7cUhaXL/DKnuvlr0Lfn07ezHp1jYZk/img.png&quot; data-alt=&quot;서버-도커 관계&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6mYcR/btsL7cUhaXL/DKnuvlr0Lfn07ezHp1jYZk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6mYcR%2FbtsL7cUhaXL%2FDKnuvlr0Lfn07ezHp1jYZk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;375&quot; data-origin-width=&quot;1030&quot; data-origin-height=&quot;614&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;서버-도커 관계&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;revenue_unit_wrap&quot;&gt;
  &lt;div class=&quot;revenue_unit_item adsense responsive&quot;&gt;
    &lt;div class=&quot;revenue_unit_info&quot;&gt;반응형&lt;/div&gt;
    &lt;script src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
    &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-host=&quot;ca-host-pub-9691043933427338&quot; data-ad-client=&quot;ca-pub-8542284842011502&quot; data-ad-format=&quot;auto&quot;&gt;&lt;/ins&gt;
    &lt;script&gt;(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Resolution Process&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;When I executed the command sh dockerRun.sh, it did not proceed with the download and completed immediately. To resolve this, I followed these steps:&lt;/p&gt;
&lt;pre id=&quot;code_1738721667770&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sh dockerRun.sh&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1449&quot; data-origin-height=&quot;324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXkWoo/btsL8JKgyoM/JE4NhVVTAQAYMPfC312YK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXkWoo/btsL8JKgyoM/JE4NhVVTAQAYMPfC312YK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXkWoo/btsL8JKgyoM/JE4NhVVTAQAYMPfC312YK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXkWoo%2FbtsL8JKgyoM%2FJE4NhVVTAQAYMPfC312YK1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1449&quot; height=&quot;324&quot; data-origin-width=&quot;1449&quot; data-origin-height=&quot;324&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;1. Stopping and Removing Running Docker Containers:&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_1738721968242&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;docker stop &amp;lt;&amp;lt;first-container-name&amp;gt;&amp;gt;
docker rm &amp;lt;&amp;lt;first-container-name&amp;gt;&amp;gt;

docker stop &amp;lt;&amp;lt;second-container-name&amp;gt;&amp;gt;
docker rm &amp;lt;&amp;lt;second-container-name&amp;gt;&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;Relaunching Docker:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #000000; text-align: left;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;After cleaning up the containers, I relaunched Docker, and the download proceeded normally, resolving the issue.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;Conclusion&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;By systematically analyzing the root cause of the problem and cleaning up the running containers before relaunching,&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;I was able to resolve the issue.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;This approach can serve as a good reference for troubleshooting Docker-related problems in the future.&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>docker</category>
      <category>docker container</category>
      <category>docker deployment fails</category>
      <category>docker down</category>
      <category>docker error</category>
      <category>docker run error</category>
      <category>docker 다운</category>
      <category>ubuntu docker</category>
      <category>도커 컨테이너</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/122</guid>
      <comments>https://nicksoon.tistory.com/entry/Docker-Program-Error-and-Solution-When-Ubuntu-Docker-Deployment-Fails#entry122comment</comments>
      <pubDate>Wed, 5 Feb 2025 11:29:25 +0900</pubDate>
    </item>
    <item>
      <title>Easy 20x20 Maze Adventure</title>
      <link>https://nicksoon.tistory.com/entry/Easy-20x20-Maze-Adventure</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;1146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biwu8d/btsL7FBHiGR/nDbudZzILH5jmdBJfbnXI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biwu8d/btsL7FBHiGR/nDbudZzILH5jmdBJfbnXI0/img.png&quot; data-alt=&quot;Maze Adventure stage 1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biwu8d/btsL7FBHiGR/nDbudZzILH5jmdBJfbnXI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbiwu8d%2FbtsL7FBHiGR%2FnDbudZzILH5jmdBJfbnXI0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;946&quot; height=&quot;1146&quot; data-origin-width=&quot;946&quot; data-origin-height=&quot;1146&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Maze Adventure stage 1&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;Stage Design for the Maze Game(Simple 20x20 Maze Layout)&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Stage Layouts&lt;/b&gt;: The game features multiple maze layouts, each represented by a 2D array containing different values. The value 1 represents a path where the player can move, while 0 represents walls that block movement. Each stage offers a unique challenge, requiring different navigation strategies.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Grid Representation&lt;/b&gt;: The maze is displayed as a grid of cells using a CSS Grid layout. Each cell has a specific size (20px by 20px) and is displayed in a visually appealing manner with gaps between the cells for better visibility.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Cell Styling&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Walls&lt;/b&gt;: Cells that are part of the wall are filled with a solid black background.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Player&lt;/b&gt;: The player's current position is indicated by a blue cell.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;End Point&lt;/b&gt;: The exit of the maze is represented by a red cell located at the bottom-right corner (cell [19, 19] of the grid).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Interactive Elements&lt;/b&gt;: Players can interact with the maze through mouse clicks on cells or keyboard inputs (arrow keys). Clicking on a cell or pressing the corresponding arrow key will attempt to move the player to that location.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Dynamic Updates&lt;/b&gt;: As the player moves through the maze, the visual representation of the maze is dynamically updated to reflect the player&amp;rsquo;s new position, enhancing the interactive experience.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Progression System&lt;/b&gt;: Upon reaching the end of a maze, a message is displayed indicating the current stage number and the time taken to complete it. The game then resets to the next stage, keeping the player engaged with new challenges.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;revenue_unit_wrap&quot;&gt;
  &lt;div class=&quot;revenue_unit_item adsense responsive&quot;&gt;
    &lt;div class=&quot;revenue_unit_info&quot;&gt;반응형&lt;/div&gt;
    &lt;script src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
    &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-host=&quot;ca-host-pub-9691043933427338&quot; data-ad-client=&quot;ca-pub-8542284842011502&quot; data-ad-format=&quot;auto&quot;&gt;&lt;/ins&gt;
    &lt;script&gt;(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;This stage design not only emphasizes interactivity and visual clarity but also encourages players to overcome obstacles and improve their maze-solving skills. If you need more details or specific aspects covered, let me know!&lt;/p&gt;
&lt;pre id=&quot;code_1738680566889&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const mazeLayouts = [
            [
                [1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1],
                [0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
                [1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0],
                [1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1],
                [1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0],
                [0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1],
                [1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1],
                [1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1],
                [1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1],
                [0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1],
                [1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1],
                [0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1],
                [1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
                [0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1],
                [1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0],
                [1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1],
                [1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1],
                [1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0],
                [1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1],
                [1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1]
            ],
	   		[ /* Second maze layout */ ],
            [ /* Third maze layout */ ],
        ];&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;932&quot; data-origin-height=&quot;1122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eKGSQW/btsL6RvZ6U4/zp6vtmC8LbPK8XvQZO8nIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eKGSQW/btsL6RvZ6U4/zp6vtmC8LbPK8XvQZO8nIK/img.png&quot; data-alt=&quot;Maze Adventure stage 2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eKGSQW/btsL6RvZ6U4/zp6vtmC8LbPK8XvQZO8nIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeKGSQW%2FbtsL6RvZ6U4%2Fzp6vtmC8LbPK8XvQZO8nIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;932&quot; height=&quot;1122&quot; data-origin-width=&quot;932&quot; data-origin-height=&quot;1122&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Maze Adventure stage 2&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;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;1. If you want to add more stages, you can add more stages.&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_1738680613320&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; let stage = 0; // Current maze stage
        let mazeLayout = mazeLayouts[stage]; // Current maze layout
        const mazeElement = document.getElementById(&quot;maze&quot;); // Maze element in DOM
        const timeElement = document.getElementById(&quot;time&quot;); // Timer element in DOM

        // Player's initial position
        let playerPosition = { x: 0, y: 0 };
        let timer = 0; // Timer for tracking duration
        let timerInterval; // Interval reference for the timer

        // Function to create the maze UI
        function createMaze() {
            mazeElement.innerHTML = ''; // Clear previous maze content
            for (let y = 0; y &amp;lt; mazeLayout.length; y++) {
                for (let x = 0; x &amp;lt; mazeLayout[y].length; x++) {
                    const cellDiv = document.createElement(&quot;div&quot;);
                    cellDiv.classList.add(&quot;cell&quot;); // Add cell class
                    if (mazeLayout[y][x] === 0) {
                        cellDiv.classList.add(&quot;wall&quot;); // Add wall class for walls
                    }
                    if (x === playerPosition.x &amp;amp;&amp;amp; y === playerPosition.y) {
                        cellDiv.classList.add(&quot;player&quot;); // Add player class for player's position
                    }
                    if (x === 19 &amp;amp;&amp;amp; y === 19) {
                        cellDiv.classList.add(&quot;end&quot;); // Add end class for the end point
                    }
                    mazeElement.appendChild(cellDiv); // Append cell to maze
                    cellDiv.addEventListener(&quot;click&quot;, () =&amp;gt; movePlayer(x, y)); // Click event for cell
                }
            }
        }&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;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;2. Add the action of the player moving&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_1738680712203&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Function to move the player
        function movePlayer(newX, newY) {
            if (newX &amp;gt;= 0 &amp;amp;&amp;amp; newX &amp;lt; 20 &amp;amp;&amp;amp; newY &amp;gt;= 0 &amp;amp;&amp;amp; newY &amp;lt; 20 &amp;amp;&amp;amp; mazeLayout[newY][newX] !== 0) {
                playerPosition.x = newX; // Update player's X position
                playerPosition.y = newY; // Update player's Y position
                createMaze(); // Rebuild the maze display
                checkWin(); // Check if the player has reached the end
            }
        }

        // Keyboard input handler
        function handleKeyPress(event) {
            switch (event.key) {
                case &quot;ArrowUp&quot;:
                    movePlayer(playerPosition.x, playerPosition.y - 1); // Move up
                    break;
                case &quot;ArrowDown&quot;:
                    movePlayer(playerPosition.x, playerPosition.y + 1); // Move down
                    break;
                case &quot;ArrowLeft&quot;:
                    movePlayer(playerPosition.x - 1, playerPosition.y); // Move left
                    break;
                case &quot;ArrowRight&quot;:
                    movePlayer(playerPosition.x + 1, playerPosition.y); // Move right
                    break;
            }
        }&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;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;3. When the plier arrives, it's done&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_1738680764717&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Function to check if the player has won
function checkWin() {
    if (playerPosition.x === 19 &amp;amp;&amp;amp; playerPosition.y === 19) { // Check if player reached the end
        clearInterval(timerInterval); // Stop the timer
        alert(`${stage}stage! time: ${timer}s`); // Alert the player's time taken
        resetGame(); // Reset the game for the next stage
    }
}&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;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;4. It's going to reset&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;pre id=&quot;code_1738680787952&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Function to reset the game state and load the next maze
function resetGame() {
    playerPosition = { x: 0, y: 0 }; // Reset player's position
    timer = 0; // Reset the timer
    timeElement.textContent = timer; // Update the timer display
    stage++; // Move to the next stage

    mazeLayout = mazeLayouts[stage]; // Load the next maze layout
    if (stage &amp;gt;= mazeLayouts.length) { // Check if all stages are completed
        alert(`All clear`); // Alert that all mazes have been cleared
        return; // Exit the function
    }
    createMaze(); // Create the new maze
    clearInterval(timerInterval); // Clear existing timer
    startTimer(); // Start the timer for the new stage
}&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;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8542284842011502&quot;&gt;&lt;/script&gt;
&lt;/p&gt;
&lt;!-- 닉순 디스플레이 광고 반응형 --&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;5. The timer is working&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_1738680814701&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  // Function to start the timer
function startTimer() {
    timerInterval = setInterval(() =&amp;gt; {
        timer++; // Increment timer every second
        timeElement.textContent = timer; // Update the displayed time
    }, 1000);
}&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;932&quot; data-origin-height=&quot;1138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bv2NH4/btsL8fo0Lcg/0aJpGKFnm7BrKLRKtdpBNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bv2NH4/btsL8fo0Lcg/0aJpGKFnm7BrKLRKtdpBNk/img.png&quot; data-alt=&quot;Maze Adventure stage3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bv2NH4/btsL8fo0Lcg/0aJpGKFnm7BrKLRKtdpBNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbv2NH4%2FbtsL8fo0Lcg%2F0aJpGKFnm7BrKLRKtdpBNk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;932&quot; height=&quot;1138&quot; data-origin-width=&quot;932&quot; data-origin-height=&quot;1138&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Maze Adventure stage3&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;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;Then, I'll start the function and add html and style&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_1738680867065&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Function to initialize and start the game
function startGame() {
    playerPosition = { x: 0, y: 0 }; // Reset player's position
    timer = 0; // Reset timer
    timeElement.textContent = timer; // Update timer display
    createMaze(); // Create the maze
    clearInterval(timerInterval); // Clear any existing timer
    startTimer(); // Start the timer
    window.addEventListener('keydown', handleKeyPress); // Add keydown event listener
}

// Start the game when the script loads
startGame();&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_1738680904199&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;style&amp;gt;
    /* Maze container and cell styles */
    #maze {
        display: grid;
        grid-template-columns: repeat(20, 20px); /* 20 columns of 20px each */
        grid-gap: 2px; /* Space between cells */
        margin: 20px auto; /* Center the maze on the page */
        border: 1px solid #000000; /* Border around the maze */
        width: max-content; /* Adjust width according to content */
    }

    .cell {
        width: 20px; /* Width of each cell */
        height: 20px; /* Height of each cell */
        border: 1px solid #00000000; /* Transparent border */
    }

    /* Cell types and their colors */
    .wall {
        background-color: black; /* Walls in the maze */
    }

    .start {
        background-color: green; /* Start point (not used in the current layout) */
    }

    .end {
        background-color: red; /* End point of the maze */
    }

    .player {
        background-color: blue; /* Player's position */
    }
&amp;lt;/style&amp;gt;


&amp;lt;div id=&quot;stage&quot;&amp;gt;1&amp;lt;/div&amp;gt; &amp;lt;!-- Displays the current stage --&amp;gt;
&amp;lt;div id=&quot;maze&quot;&amp;gt;&amp;lt;/div&amp;gt; &amp;lt;!-- The maze will be rendered here --&amp;gt;
&amp;lt;div id=&quot;timer&quot;&amp;gt;Time: &amp;lt;span id=&quot;time&quot;&amp;gt;0&amp;lt;/span&amp;gt; seconds&amp;lt;/div&amp;gt; &amp;lt;!-- Timer display --&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;size16&quot;&gt;#adventure&amp;nbsp;corn&amp;nbsp;maze&amp;nbsp;#adventure&amp;nbsp;maze&amp;nbsp;#corn&amp;nbsp;maze&amp;nbsp;and&amp;nbsp;pumpkin&amp;nbsp;patch&amp;nbsp;#corn&amp;nbsp;mazes&amp;nbsp;#corn&amp;nbsp;mazes&amp;nbsp;and&amp;nbsp;pumpkin&amp;nbsp;patches&amp;nbsp;#cornfield&amp;nbsp;maze&amp;nbsp;#family&amp;nbsp;fun&amp;nbsp;center&amp;nbsp;lakeland&amp;nbsp;#houston&amp;nbsp;attractions&amp;nbsp;for&amp;nbsp;families&amp;nbsp;#kersey&amp;nbsp;valley&amp;nbsp;corn&amp;nbsp;maze&amp;nbsp;#kersey&amp;nbsp;valley&amp;nbsp;maize&amp;nbsp;#kersey&amp;nbsp;valley&amp;nbsp;maize&amp;nbsp;adventure&amp;nbsp;#kersey&amp;nbsp;valley&amp;nbsp;maize&amp;nbsp;adventure&amp;nbsp;photos&amp;nbsp;#maize&amp;nbsp;adventure&amp;nbsp;#maize&amp;nbsp;adventures&amp;nbsp;#maze&amp;nbsp;adventures&amp;nbsp;#pumpkin&amp;nbsp;patch&amp;nbsp;and&amp;nbsp;corn&amp;nbsp;maze&amp;nbsp;#pumpkin&amp;nbsp;patch&amp;nbsp;hay&amp;nbsp;rides&amp;nbsp;#pumpkin&amp;nbsp;patch&amp;nbsp;with&amp;nbsp;corn&amp;nbsp;maze&amp;nbsp;#skeeters&amp;nbsp;maze&amp;nbsp;adventure&amp;nbsp;#things&amp;nbsp;to&amp;nbsp;do&amp;nbsp;in&amp;nbsp;sugar&amp;nbsp;land&lt;/p&gt;</description>
      <category>개발/게임 만드는 일지</category>
      <category>adventure corn maze</category>
      <category>adventure maze</category>
      <category>corn maze and pumpkin patch</category>
      <category>corn mazes</category>
      <category>corn mazes and pumpkin patches</category>
      <category>cornfield maze</category>
      <category>family fun center lakeland</category>
      <category>houston attractions for families</category>
      <category>kersey valley corn maze</category>
      <category>kersey valley maize</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/121</guid>
      <comments>https://nicksoon.tistory.com/entry/Easy-20x20-Maze-Adventure#entry121comment</comments>
      <pubDate>Tue, 4 Feb 2025 23:40:44 +0900</pubDate>
    </item>
    <item>
      <title>node 콘솔 입력 받기</title>
      <link>https://nicksoon.tistory.com/entry/node-%EC%BD%98%EC%86%94-%EC%9E%85%EB%A0%A5-%EB%B0%9B%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;테스트용으로 작업하다가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;node 서버까지는 필요 없는데&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력은 받아야 할 것 같아 노트합니다&lt;/p&gt;
&lt;p data-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_1738635199887&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import readline from &quot;readline&quot;;

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

// 입력 대기 함수
function askQuestion(query) {
    return new Promise(resolve =&amp;gt; rl.question(query, resolve));
}&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_1738635037406&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let key = 0;
let startKeyword = &quot;&quot;;
let isExit = false
// 입력 대기
do {
    console.log(
        `
1 : 키워드 등록하기
2 : 키워드 찾기
3 : 경로 찾기
4 : 모든 값
5 : 나가기
`);

    key = parseInt(await askQuestion('메뉴 선택 (1-4): '));

    switch (key) {
        case 1:
            // 키워드를 입력 받는다
            startKeyword = await askQuestion('등록할 키워드 입력: ');
            await recursiveKeywordFetch(startKeyword);
            break;

        case 2:
            // 키워드를 입력 받는다
            const searchKeyword = await askQuestion('찾을 키워드 입력: ');
            // 여기에 키워드 찾기 로직 추가
            console.log(`찾고 있는 키워드: ${searchKeyword}`);
            await getNodesAndRelationships(searchKeyword);
            break;

        case 3:
            // 여기에 모든 값 출력 로직 추가
            console.log('경로 값 출력');
            const fistKeyword = await askQuestion('시작 키워드 입력: ');
            const secondKeyword = await askQuestion('끝 키워드 입력: ');
            await getIntentKeyword(fistKeyword,secondKeyword);
            break;
        case 4:
            // 여기에 모든 값 출력 로직 추가
            console.log('모든 값 출력');
            await getAllData();
            break;

        case 5:
            isExit = true;
            console.log('프로그램을 종료합니다.');
            break;

        default:
            console.log('잘못된 입력입니다. 다시 선택해 주세요.');
            break;
    }



} while (!isExit);&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;415&quot; data-origin-height=&quot;266&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NVYrh/btsL5BUswFM/5JS9UyYdqDSflLdK9SNMs0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NVYrh/btsL5BUswFM/5JS9UyYdqDSflLdK9SNMs0/img.png&quot; data-alt=&quot;입력 받기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NVYrh/btsL5BUswFM/5JS9UyYdqDSflLdK9SNMs0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNVYrh%2FbtsL5BUswFM%2F5JS9UyYdqDSflLdK9SNMs0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;415&quot; height=&quot;266&quot; data-origin-width=&quot;415&quot; data-origin-height=&quot;266&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;입력 받기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;317&quot; data-origin-height=&quot;260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tS12X/btsL6rjdJb1/Mkcig7MiARNwpgOr8UD9Ik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tS12X/btsL6rjdJb1/Mkcig7MiARNwpgOr8UD9Ik/img.png&quot; data-alt=&quot;node 입력 받기 키워드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tS12X/btsL6rjdJb1/Mkcig7MiARNwpgOr8UD9Ik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtS12X%2FbtsL6rjdJb1%2FMkcig7MiARNwpgOr8UD9Ik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;317&quot; height=&quot;260&quot; data-origin-width=&quot;317&quot; data-origin-height=&quot;260&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;node 입력 받기 키워드&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;반복문으로 지속적으로 진행을 하도록 했습니다&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;&amp;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;#javascript&amp;nbsp;readline#javascript&amp;nbsp;입력&amp;nbsp;받기#javascript&amp;nbsp;입력받기#js&amp;nbsp;readline#js&amp;nbsp;입력#js&amp;nbsp;입력받기#node&amp;nbsp;js&amp;nbsp;input#node&amp;nbsp;js&amp;nbsp;prompt#node&amp;nbsp;js&amp;nbsp;readline#node&amp;nbsp;prompt#node&amp;nbsp;readline#node.js&amp;nbsp;input#node.js&amp;nbsp;prompt#node.js&amp;nbsp;readline#nodejs&amp;nbsp;readline#readline&amp;nbsp;javascript#readline&amp;nbsp;js#자바&amp;nbsp;스크립트&amp;nbsp;입력#자바&amp;nbsp;스크립트&amp;nbsp;입력받기#자바&amp;nbsp;스크립트&amp;nbsp;콘솔&amp;nbsp;입력#자바스크립트&amp;nbsp;readline#자바스크립트&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;</description>
      <category>개발/개발 필기</category>
      <category>javascript readline</category>
      <category>javascript 입력 받기</category>
      <category>js 입력</category>
      <category>node js input</category>
      <category>node readline</category>
      <category>node 개발</category>
      <category>node 콘솔 입력</category>
      <category>readLine</category>
      <category>자바 스크립트 입력받기</category>
      <category>콘솔 입력</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/120</guid>
      <comments>https://nicksoon.tistory.com/entry/node-%EC%BD%98%EC%86%94-%EC%9E%85%EB%A0%A5-%EB%B0%9B%EA%B8%B0#entry120comment</comments>
      <pubDate>Tue, 4 Feb 2025 11:18:44 +0900</pubDate>
    </item>
    <item>
      <title>'가비아' '티스토리' 연결 및 하위 도메인</title>
      <link>https://nicksoon.tistory.com/entry/%EA%B0%80%EB%B9%84%EC%95%84-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC-%EC%97%B0%EA%B2%B0-%EB%B0%8F-%ED%95%98%EC%9C%84-%EB%8F%84%EB%A9%94%EC%9D%B8</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;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;1. 하위 도메인 설정의 장점&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;가비아에서 도메인을 구매한 후, 하위 도메인을 티스토리와 연결하는 것은 꽤 간편합니다. 하위 도메인을 생성하고 DNS 세팅에서 CNAME으로 설정하는 방식은 관리가 용이하다는 장점이 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;2. 서버 호스팅과의 권한 문제&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;만약 서버 호스트에서의 작업이 원활하지 않을 경우, 예를 들어 NGINX와 같은 웹 서버의 설정을 하는 것이 어렵다면, 더 나은 방안으로는 도메인을 구매한 곳에서 직접 DNS 세팅을 통해 관리를 하는 것입니다. 이렇게 하면 복잡한 서버 설정을 건너뛰고, 간단하게 연결을 완료할 수 있습니다.&lt;/p&gt;
&lt;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;3. 서버 관리가 필요한 경우&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;물론, 회사나 서버에서 관리가 이루어진다면 큰 문제가 없겠지만, 개인적으로 직접 관리하고 싶다면 DNS 설정을 통해 하위 도메인을 연결하는 것이 더 효율적입니다. 저도 NGINX에서 https 세팅을 직접 해본 경험이 있지만, 도메인을 구매한 곳에서 제공하는 서비스를 이용하는 것이 훨씬 더 간편하다는 것을 느꼈습니다.&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;티스토리 '도메인 연결'&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 가비아에서 마이 가비아를 들어갑니다. - DNS 관리툴을 들어갑니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2442&quot; data-origin-height=&quot;1522&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oZmOs/btsL4G8QMt6/xnwIM1Wr6jHy5z03gIh3h1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oZmOs/btsL4G8QMt6/xnwIM1Wr6jHy5z03gIh3h1/img.png&quot; data-alt=&quot;마이 가비아&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oZmOs/btsL4G8QMt6/xnwIM1Wr6jHy5z03gIh3h1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoZmOs%2FbtsL4G8QMt6%2FxnwIM1Wr6jHy5z03gIh3h1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2442&quot; height=&quot;1522&quot; data-origin-width=&quot;2442&quot; data-origin-height=&quot;1522&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;마이 가비아&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;설정할 도메인 선택 - 도메인 연결&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2617&quot; data-origin-height=&quot;940&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJhBfK/btsL5u0UAqM/FSJ4Y0SpY1PAMxHk7m3hp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJhBfK/btsL5u0UAqM/FSJ4Y0SpY1PAMxHk7m3hp1/img.png&quot; data-alt=&quot;DNS 관리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJhBfK/btsL5u0UAqM/FSJ4Y0SpY1PAMxHk7m3hp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJhBfK%2FbtsL5u0UAqM%2FFSJ4Y0SpY1PAMxHk7m3hp1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2617&quot; height=&quot;940&quot; data-origin-width=&quot;2617&quot; data-origin-height=&quot;940&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;DNS 관리&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;span style=&quot;color: #000000; text-align: center;&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;2756&quot; data-origin-height=&quot;1304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KlFlG/btsL4MHTipA/6Lg6O1BDl7GawkVbflmei1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KlFlG/btsL4MHTipA/6Lg6O1BDl7GawkVbflmei1/img.png&quot; data-alt=&quot;연결할 블로그 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KlFlG/btsL4MHTipA/6Lg6O1BDl7GawkVbflmei1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKlFlG%2FbtsL4MHTipA%2F6Lg6O1BDl7GawkVbflmei1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2756&quot; height=&quot;1304&quot; data-origin-width=&quot;2756&quot; data-origin-height=&quot;1304&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;연결할 블로그 선택&lt;/figcaption&gt;
&lt;/figure&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2450&quot; data-origin-height=&quot;784&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xTqet/btsL5jL0WNP/Ok7OAkG05WHgQCu5KMt9Y0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xTqet/btsL5jL0WNP/Ok7OAkG05WHgQCu5KMt9Y0/img.png&quot; data-alt=&quot;티스토리 블로그 세팅&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xTqet/btsL5jL0WNP/Ok7OAkG05WHgQCu5KMt9Y0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxTqet%2FbtsL5jL0WNP%2FOk7OAkG05WHgQCu5KMt9Y0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2450&quot; height=&quot;784&quot; data-origin-width=&quot;2450&quot; data-origin-height=&quot;784&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;티스토리 블로그 세팅&lt;/figcaption&gt;
&lt;/figure&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;a href=&quot;https://njcin.co.kr/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://njcin.co.kr/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1738487398896&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;나예그안&quot; data-og-description=&quot;구글 SEO 최적화, 구글 연관키워드 등 여러 정보 공유 드려요&quot; data-og-host=&quot;njcin.co.kr&quot; data-og-source-url=&quot;https://njcin.co.kr/&quot; data-og-url=&quot;https://njcin.co.kr&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/1vUbs/hyYb8qGTik/XKCeq0o7YRC1wyrnyKKq61/img.jpg?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bjpVKW/hyYckxTsB2/H9oNVMvWdsI07XCCsbyIq1/img.jpg?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://njcin.co.kr/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://njcin.co.kr/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/1vUbs/hyYb8qGTik/XKCeq0o7YRC1wyrnyKKq61/img.jpg?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bjpVKW/hyYckxTsB2/H9oNVMvWdsI07XCCsbyIq1/img.jpg?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&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;나예그안&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;구글 SEO 최적화, 구글 연관키워드 등 여러 정보 공유 드려요&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;njcin.co.kr&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 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 class=&quot;revenue_unit_wrap&quot;&gt;
  &lt;div class=&quot;revenue_unit_item adsense responsive&quot;&gt;
    &lt;div class=&quot;revenue_unit_info&quot;&gt;반응형&lt;/div&gt;
    &lt;script src=&quot;//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js&quot; async=&quot;async&quot;&gt;&lt;/script&gt;
    &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-host=&quot;ca-host-pub-9691043933427338&quot; data-ad-client=&quot;ca-pub-8542284842011502&quot; data-ad-format=&quot;auto&quot;&gt;&lt;/ins&gt;
    &lt;script&gt;(adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;가비아&amp;nbsp; CNAME 설정&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2870&quot; data-origin-height=&quot;698&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bddT07/btsL5A7NeGi/bkCdMZMGq6wapMkhOLiaQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bddT07/btsL5A7NeGi/bkCdMZMGq6wapMkhOLiaQk/img.png&quot; data-alt=&quot;가비아 DNS 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bddT07/btsL5A7NeGi/bkCdMZMGq6wapMkhOLiaQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbddT07%2FbtsL5A7NeGi%2FbkCdMZMGq6wapMkhOLiaQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2870&quot; height=&quot;698&quot; data-origin-width=&quot;2870&quot; data-origin-height=&quot;698&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가비아 DNS 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;가비아 DNS 관리 - 도메인 설정에서 레코드 수정 이동&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2870&quot; data-origin-height=&quot;1462&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UQfLN/btsL2SCCM3T/5583IP6KpdDgkSVChqGPwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UQfLN/btsL2SCCM3T/5583IP6KpdDgkSVChqGPwk/img.png&quot; data-alt=&quot;가비아 레코드 수정 클릭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UQfLN/btsL2SCCM3T/5583IP6KpdDgkSVChqGPwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUQfLN%2FbtsL2SCCM3T%2F5583IP6KpdDgkSVChqGPwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2870&quot; height=&quot;1462&quot; data-origin-width=&quot;2870&quot; data-origin-height=&quot;1462&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가비아 레코드 수정 클릭&lt;/figcaption&gt;
&lt;/figure&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1806&quot; data-origin-height=&quot;790&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgCi3o/btsL4aoZOM9/MP6KxyWvLOePKMdSnQ8d9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgCi3o/btsL4aoZOM9/MP6KxyWvLOePKMdSnQ8d9K/img.png&quot; data-alt=&quot;가비아 레코드 수정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgCi3o/btsL4aoZOM9/MP6KxyWvLOePKMdSnQ8d9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgCi3o%2FbtsL4aoZOM9%2FMP6KxyWvLOePKMdSnQ8d9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1806&quot; height=&quot;790&quot; data-origin-width=&quot;1806&quot; data-origin-height=&quot;790&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가비아 레코드 수정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;DNS 에서 레코드 추가에서 타입을 따라 내용을 추가합니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1820&quot; data-origin-height=&quot;916&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZYf0v/btsL4PYMRBJ/C1jldXsspXUPyWjwSXEo3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZYf0v/btsL4PYMRBJ/C1jldXsspXUPyWjwSXEo3K/img.png&quot; data-alt=&quot;가비아 레코드 내용 추가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZYf0v/btsL4PYMRBJ/C1jldXsspXUPyWjwSXEo3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZYf0v%2FbtsL4PYMRBJ%2FC1jldXsspXUPyWjwSXEo3K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1820&quot; height=&quot;916&quot; data-origin-width=&quot;1820&quot; data-origin-height=&quot;916&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가비아 레코드 내용 추가&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;DNS 레코드 유형 설명 및 예시&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;A (Address Record) - IP 주소&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;설명:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;A 레코드는 도메인을 IPv4 주소에 매핑합니다. 사용자가 도메인을 입력할 때, 해당 도메인이 어떤 서버로 연결될지를 결정합니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예시:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;example.com이&lt;span&gt;&amp;nbsp;&lt;/span&gt;192.0.2.1이라는 IP 주소로 연결된다면, A 레코드는 다음과 같이 설정됩니다.
&lt;div style=&quot;background-color: #000000; color: #000000;&quot;&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;text&lt;/span&gt;
&lt;div style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #000000; color: #000000;&quot;&gt;Copy&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;pre class=&quot;css&quot; style=&quot;color: #000000;&quot;&gt;&lt;code&gt;example.com.     IN     A     192.0.2.1
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MX (Mail Exchange) - 메일 호스트&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;설명:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;MX 레코드는 도메인의 이메일을 처리하는 메일 서버를 지정합니다. 이메일을 해당 도메인으로 보내는 경우, 어떤 서버가 해당 이메일을 받아야 하는지를 설정합니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예시:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;example.com의 메일 호스트가&lt;span&gt;&amp;nbsp;&lt;/span&gt;mail.example.com에 있다면 MX 레코드는 다음과 같이 설정됩니다.
&lt;div style=&quot;background-color: #000000; color: #000000;&quot;&gt;
&lt;pre class=&quot;css&quot; style=&quot;color: #000000;&quot;&gt;&lt;code&gt;example.com.     IN     MX     10 mail.example.com.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;CNAME (Canonical Name) - 값, 위치&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;설명:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;CNAME 레코드는 도메인의 별칭을 설정합니다. 다른 도메인이 실제 도메인을 가리킬 수 있도록 하며, 여러 도메인이 동일한 IP 주소를 공유할 수 있게 해줍니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예시:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;www.example.com이&lt;span&gt;&amp;nbsp;&lt;/span&gt;example.com의 별칭인 경우, CNAME 레코드는 다음과 같이 설정됩니다.
&lt;div style=&quot;background-color: #000000; color: #000000;&quot;&gt;
&lt;pre class=&quot;css&quot; style=&quot;color: #000000;&quot;&gt;&lt;code&gt;www.example.com.     IN     CNAME     example.com.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;TXT (Text Record) - DNS 설정&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;설명:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;TXT 레코드는 도메인에 대한 추가 정보를 저장할 수 있습니다. 주로 SPF(발신자 정책 프레임워크)나 DKIM(도메인키 식별 메일)과 같은 인증 정보를 제공하는 데 사용됩니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예시:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;도메인에 대한 SPF 정보를 설정하는 TXT 레코드는 다음과 같을 수 있습니다.
&lt;div style=&quot;background-color: #000000; color: #000000;&quot;&gt;
&lt;pre class=&quot;maxima&quot; style=&quot;color: #000000;&quot;&gt;&lt;code&gt;example.com.     IN     TXT     &quot;v=spf1 include:example.com -all&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;SRV (Service Record)&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;설명:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;SRV 레코드는 특정 서비스를 제공하는 서버의 위치를 지정합니다. 주로 VoIP, IM, 또는 다른 프로토콜에 대한 서비스에 사용됩니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;예시:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;예를 들어, SIP 서비스를 위한 SRV 레코드는 다음과 같이 설정될 수 있습니다.
&lt;div style=&quot;background-color: #000000; color: #000000;&quot;&gt;
&lt;pre class=&quot;css&quot; style=&quot;color: #000000;&quot;&gt;&lt;code&gt;_sip._tcp.example.com.     IN     SRV     10 60 5060 sipserver.example.com.
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이와 같이 각 DNS 레코드는 도메인과 그에 관련된 서비스의 동작을 제어하는 데 중요한 역할을 합니다. 필요에 따라 적절한 설정을 통해 도메인을 관리하세요!&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2386&quot; data-origin-height=&quot;756&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6DZEh/btsL4MVq2bd/EkwO9ehFayZmX7jtp5HQs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6DZEh/btsL4MVq2bd/EkwO9ehFayZmX7jtp5HQs1/img.png&quot; data-alt=&quot;티스토리 블로그 도메인 설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6DZEh/btsL4MVq2bd/EkwO9ehFayZmX7jtp5HQs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6DZEh%2FbtsL4MVq2bd%2FEkwO9ehFayZmX7jtp5HQs1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2386&quot; height=&quot;756&quot; data-origin-width=&quot;2386&quot; data-origin-height=&quot;756&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;티스토리 블로그 도메인 설정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과 &lt;a href=&quot;https://money.njcin.co.kr/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://money.njcin.co.kr/&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;h2 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;가비아와 티스토리를 연결하는 과정에서 하위 도메인을 활용하면 여러 가지 장점을 누릴 수 있습니다. DNS 설정을 통해 간편하게 연결하는 방법을 활용해 보세요. 이를 통해 더욱 수월하게 블로그 운영을 할 수 있을 것입니다.&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>가비아</category>
      <category>가비아 cname</category>
      <category>가비아 dns 세팅</category>
      <category>가비아 도메인</category>
      <category>가비아 도메인 세팅</category>
      <category>가비아 세팅</category>
      <category>가비아 티스토리</category>
      <category>가비아 하위도메인</category>
      <category>티스토리</category>
      <category>티스토리 하위 도메인</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/119</guid>
      <comments>https://nicksoon.tistory.com/entry/%EA%B0%80%EB%B9%84%EC%95%84-%ED%8B%B0%EC%8A%A4%ED%86%A0%EB%A6%AC-%EC%97%B0%EA%B2%B0-%EB%B0%8F-%ED%95%98%EC%9C%84-%EB%8F%84%EB%A9%94%EC%9D%B8#entry119comment</comments>
      <pubDate>Sun, 2 Feb 2025 18:13:25 +0900</pubDate>
    </item>
    <item>
      <title>PM2 사용법: Node.js 애플리케이션 관리 및 모니터링</title>
      <link>https://nicksoon.tistory.com/entry/PM2-%EC%82%AC%EC%9A%A9%EB%B2%95-Nodejs-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EA%B4%80%EB%A6%AC-%EB%B0%8F-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81</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;a title=&quot;우분투 설치하러가기&quot; href=&quot;https://nickdeveloper.co.kr/entry/%EC%9A%B0%EB%B6%84%ED%88%AC%EC%97%90%EC%84%9C-Nodejs%EC%99%80-PM2%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EB%AC%B4%EC%A4%91%EB%8B%A8-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%8B%A4%ED%96%89-%EB%B0%A9%EB%B2%95&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;우분투 설치하러가기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1737420877993&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;우분투에서 Node.js와 PM2를 사용한 무중단 애플리케이션 설치 방법&quot; data-og-description=&quot;1. curl 설치Node.js 설치를 위해 먼저 curl이 필요합니다. 아래 명령을 사용하여 curl을 설치합니다.sudo apt updatesudo apt install curl&amp;nbsp;2. Node.js 설치 스크립트 추가Node.js의 버전은 18.x 또는 20.x 중 선택하여 &quot; data-og-host=&quot;nickdeveloper.co.kr&quot; data-og-source-url=&quot;https://nickdeveloper.co.kr/entry/%EC%9A%B0%EB%B6%84%ED%88%AC%EC%97%90%EC%84%9C-Nodejs%EC%99%80-PM2%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EB%AC%B4%EC%A4%91%EB%8B%A8-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%8B%A4%ED%96%89-%EB%B0%A9%EB%B2%95&quot; data-og-url=&quot;https://nickdeveloper.co.kr/entry/%EC%9A%B0%EB%B6%84%ED%88%AC%EC%97%90%EC%84%9C-Nodejs%EC%99%80-PM2%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EB%AC%B4%EC%A4%91%EB%8B%A8-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%8B%A4%ED%96%89-%EB%B0%A9%EB%B2%95&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/R3XzK/hyX4pUurXK/enXlCBKsOFpQ33qM2q3yZ0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cU00eb/hyX4kr65J9/gg1LgX3yKRZR5GHcw8eCI1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://nickdeveloper.co.kr/entry/%EC%9A%B0%EB%B6%84%ED%88%AC%EC%97%90%EC%84%9C-Nodejs%EC%99%80-PM2%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EB%AC%B4%EC%A4%91%EB%8B%A8-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%8B%A4%ED%96%89-%EB%B0%A9%EB%B2%95&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://nickdeveloper.co.kr/entry/%EC%9A%B0%EB%B6%84%ED%88%AC%EC%97%90%EC%84%9C-Nodejs%EC%99%80-PM2%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%9C-%EB%AC%B4%EC%A4%91%EB%8B%A8-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EC%8B%A4%ED%96%89-%EB%B0%A9%EB%B2%95&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/R3XzK/hyX4pUurXK/enXlCBKsOFpQ33qM2q3yZ0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/cU00eb/hyX4kr65J9/gg1LgX3yKRZR5GHcw8eCI1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800');&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;우분투에서 Node.js와 PM2를 사용한 무중단 애플리케이션 설치 방법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;1. curl 설치Node.js 설치를 위해 먼저 curl이 필요합니다. 아래 명령을 사용하여 curl을 설치합니다.sudo apt updatesudo apt install curl&amp;nbsp;2. Node.js 설치 스크립트 추가Node.js의 버전은 18.x 또는 20.x 중 선택하여&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;nickdeveloper.co.kr&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;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;사실, PM2는 제가 자주 사용하는 도구 중 하나입니다. &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;&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;&lt;/p&gt;
&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;그래서 이번 기회에 저만의 PM2 사용법을 정리해 보려고 합니다.&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;&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;&lt;/p&gt;
&lt;pre id=&quot;code_1737421098084&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;cd your-work-folder&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 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이제 PM2로 Node.js 애플리케이션을 실행해 보겠습니다. &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;&amp;lt;your-app.js&amp;gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;에 맞추어&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt; 아래 명령어를 입력하면 됩니다:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1737421240280&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pm2 start &amp;lt;your-app.js&amp;gt;&lt;/code&gt;&lt;/pre&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;&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;PM2는 이 애플리케이션을 백그라운드에서 관리하며, &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;&lt;/p&gt;
&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;&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;&lt;/p&gt;
&lt;pre id=&quot;code_1737421273194&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pm2 monit&lt;/code&gt;&lt;/pre&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;&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;터미널 화면에 현재 실행 중인 애플리케이션들의 상태와 CPU, &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;&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;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1931&quot; data-origin-height=&quot;1036&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mgFgH/btsLTv1dm7n/RTaNpz0OuPlPy5e8s0W7HK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mgFgH/btsLTv1dm7n/RTaNpz0OuPlPy5e8s0W7HK/img.png&quot; data-alt=&quot;윈도우 pm2 실행 이미지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mgFgH/btsLTv1dm7n/RTaNpz0OuPlPy5e8s0W7HK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmgFgH%2FbtsLTv1dm7n%2FRTaNpz0OuPlPy5e8s0W7HK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;468&quot; data-origin-width=&quot;1931&quot; data-origin-height=&quot;1036&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;윈도우 pm2 실행 이미지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이 정보들을 통해 애플리케이션의 성능을 체크하고 필요에 따라 조치를 취할 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;PM2는 이렇게 애플리케이션의 상태를 간편하게 관리하고 모니터링할 수 있는 유용한 도구입니다.&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: #ee2323; text-align: start;&quot;&gt;나가고 싶다면 Ctrl + c 입니다&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;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;애플리케이션 멈추기&lt;/h3&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;아래 명령어를 사용하세요.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;lt;app-id&amp;gt;는 pm2 list 명령어로 확인한 애플리케이션의 ID를 의미합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1737421532085&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pm2 stop &amp;lt;app-id&amp;gt;

// 전체 app을 멈추고 싶다면
pm2 stop all

// 이름이 길 경우 번호로
pm2 stop 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;애플리케이션 재실행하기&lt;/h3&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;pre id=&quot;code_1737421659241&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pm2 restart &amp;lt;app-id&amp;gt;

// 전체 app을 재실행하고 싶다면
pm2 restart all

// 이름이 길 경우 번호로
pm2 restart 1&lt;/code&gt;&lt;/pre&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;애플리케이션 삭제하기&lt;/h3&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;pre id=&quot;code_1737421746711&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pm2 delete &amp;lt;app-id&amp;gt;

// 전체 app을 삭제하고 싶다면
pm2 delete all

// 이름이 길 경우 번호로
pm2 delete 1&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이 명령어를 실행하면 애플리케이션이 PM2 관리 목록에서 제거됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;현재 실행 중인 애플리케이션 리스트 확인하기&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;PM2로 실행 중인 모든 애플리케이션의 상태를 확인하려면 pm2 list 명령어를 사용합니다. 이 명령어를 입력하면 현재 실행 중인 애플리케이션의 목록과 그 상태를 한 눈에 볼 수 있습니다:&lt;/p&gt;
&lt;pre id=&quot;code_1737421972156&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pm2 list&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1062&quot; data-origin-height=&quot;112&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cughVU/btsLTrdGlN2/jVbJkM7gOXHu8dGtoC6UAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cughVU/btsLTrdGlN2/jVbJkM7gOXHu8dGtoC6UAK/img.png&quot; data-alt=&quot;윈도우 pm2 list 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cughVU/btsLTrdGlN2/jVbJkM7gOXHu8dGtoC6UAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcughVU%2FbtsLTrdGlN2%2FjVbJkM7gOXHu8dGtoC6UAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1062&quot; height=&quot;112&quot; data-origin-width=&quot;1062&quot; data-origin-height=&quot;112&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;윈도우 pm2 list 결과&lt;/figcaption&gt;
&lt;/figure&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;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 style=&quot;color: #000000;&quot;&gt;&lt;b&gt;App name&lt;/b&gt;: 애플리케이션 이름&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;id&lt;/b&gt;: 프로세스 ID&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;mode&lt;/b&gt;: 실행 모드 (fork 또는 cluster)&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;status&lt;/b&gt;: 애플리케이션의 현재 상태 (online, stopped 등)&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;cpu&lt;/b&gt;: CPU 사용량&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;memory&lt;/b&gt;: 메모리 사용량&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;마무리&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이로써 PM2를 사용하여 Node.js 애플리케이션을 실행하고 관리하는 방법을 알아보았습니다. PM2는 애플리케이션의 상태를 쉽게 모니터링하고, 필요할 때 멈추거나 재실행하며, 삭제하는 등의 작업을 간편하게 할 수 있게 해주는 유용한 도구입니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;앞으로 PM2를 활용하여 애플리케이션 관리의 효율성을 높이시기 바랍니다. 혹시 추가적인 질문이나 도움이 필요하시면 언제든지 문의해 주세요! 감사합니다.&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>node.js pm2</category>
      <category>pm2</category>
      <category>pm2 list</category>
      <category>pm2 monit</category>
      <category>pm2 start</category>
      <category>pm2 사용법</category>
      <category>pm2 실행</category>
      <category>pm2 실행 stop</category>
      <category>pm2 실행 명령어</category>
      <category>pm2 실행 모니터링</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/118</guid>
      <comments>https://nicksoon.tistory.com/entry/PM2-%EC%82%AC%EC%9A%A9%EB%B2%95-Nodejs-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98-%EA%B4%80%EB%A6%AC-%EB%B0%8F-%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81#entry118comment</comments>
      <pubDate>Tue, 21 Jan 2025 10:14:33 +0900</pubDate>
    </item>
    <item>
      <title>chart.js 버튼 이벤트 예제</title>
      <link>https://nicksoon.tistory.com/entry/chartjs-%EB%B2%84%ED%8A%BC-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%98%88%EC%A0%9C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Chart.js&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;를 사용하여 데이터 시각화를 구현할 때,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt; Chart.js에서 쉽게 보는 예제를 정리했습니다&lt;/span&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;랜덤화 (Randomize)&lt;/li&gt;
&lt;li&gt;데이터셋 추가 (Add Dataset)&lt;/li&gt;
&lt;li&gt;데이터 추가 (Add Data)&lt;/li&gt;
&lt;li&gt;데이터셋 제거 (Remove Dataset)&lt;/li&gt;
&lt;li&gt;데이터 제거 (Remove Data) &amp;nbsp;&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;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;같은 주요 액션을 정리했습니다&lt;/span&gt;&lt;/p&gt;
&lt;div id=&quot;code_1737384404530&quot; data-ke-type=&quot;html&quot; data-source=&quot;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang=&amp;quot;ko&amp;quot;&amp;gt;

&amp;lt;head&amp;gt;
    &amp;lt;meta charset=&amp;quot;UTF-8&amp;quot;&amp;gt;
    &amp;lt;meta name=&amp;quot;viewport&amp;quot; content=&amp;quot;width=device-width, initial-scale=1.0&amp;quot;&amp;gt;
    &amp;lt;title&amp;gt;Document&amp;lt;/title&amp;gt;
    &amp;lt;script src=&amp;quot;https://cdn.jsdelivr.net/npm/chart.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;!-- Zoom 플러그인 --&amp;gt;
    &amp;lt;script src=&amp;quot;https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;/head&amp;gt;

&amp;lt;body&amp;gt;
    &amp;lt;div style=&amp;quot;width: 800px; height: 400px;&amp;quot;&amp;gt;
        &amp;lt;!-- chart가 그려질 canvas를 생성 --&amp;gt;
        &amp;lt;canvas id=&amp;quot;myChart&amp;quot; width=&amp;quot;800&amp;quot; height=&amp;quot;400&amp;quot;&amp;gt;&amp;lt;/canvas&amp;gt;
    &amp;lt;/div&amp;gt;

    &amp;lt;button id=&amp;quot;randomize&amp;quot;&amp;gt;Randomize&amp;lt;/button&amp;gt;
    &amp;lt;button id=&amp;quot;adddataset&amp;quot;&amp;gt;Add Dataset&amp;lt;/button&amp;gt;
    &amp;lt;button id=&amp;quot;adddata&amp;quot;&amp;gt;Add Data&amp;lt;/button&amp;gt;
    &amp;lt;button id=&amp;quot;removedataset&amp;quot;&amp;gt;Remove Dataset&amp;lt;/button&amp;gt;
    &amp;lt;button id=&amp;quot;removedata&amp;quot;&amp;gt;Remove Data&amp;lt;/button&amp;gt;

    &amp;lt;script&amp;gt;
        document.addEventListener('DOMContentLoaded', () =&amp;gt; {
            const Utils = {
                numbers({ count, min, max }) {
                    return Array.from({ length: count }, () =&amp;gt; Math.floor(Math.random() * (max - min + 1)) + min);
                },
                months({ count }) {
                    return Array.from({ length: count }, (_, i) =&amp;gt; new Date(0, i).toLocaleString('default', { month: 'long' }));
                },
                namedColor(index) {
                    const colors = ['red', 'blue', 'green', 'yellow', 'orange', 'purple', 'cyan'];
                    return colors[index % colors.length];
                },
                transparentize(color, opacity) {
                    const rgb = color.replace(/rgba?/, '').replace(/[^\d,]/g, '').split(',').map(Number);
                    return &amp;#96;rgba(${rgb.join(',')}, ${opacity})&amp;#96;;
                }
            };


            const actions = [
                {
                    // 데이터의 값을 랜덤화하는 액션
                    name: 'Randomize',
                    handler: (chart) =&amp;gt; {
                        // 각 데이터셋에 대해
                        chart.data.datasets.forEach(dataset =&amp;gt; {
                            // 랜덤한 데이터 생성 (최소 -100, 최대 100)
                            dataset.data = Utils.numbers({ count: chart.data.labels.length, min: -100, max: 100 });
                        });
                        // 차트를 업데이트하여 시각적으로 반영
                        chart.update();
                    }
                },
                {
                    // 새로운 데이터셋을 추가하는 액션
                    name: 'Add Dataset',
                    handler: (chart) =&amp;gt; {
                        const data = chart.data;
                        // 데이터셋 수에 따라 새로운 색상을 결정
                        const dsColor = Utils.namedColor(data.datasets.length);
                        const newDataset = {
                            // 새로운 데이터셋의 이름 설정
                            label: 'Dataset ' + (data.datasets.length + 1),
                            // 색상 설정 (투명하게)
                            backgroundColor: Utils.transparentize(dsColor, 0.5),
                            borderColor: dsColor,
                            borderWidth: 1,
                            // 랜덤 데이터 생성 (기존 레이블 수와 같은 수)
                            data: Utils.numbers({ count: data.labels.length, min: -100, max: 100 }),
                        };
                        // 데이터셋을 리스트에 추가
                        data.datasets.push(newDataset);
                        // 차트를 업데이트하여 시각적으로 반영
                        chart.update();
                    }
                },
                {
                    // 데이터에 새로운 값을 추가하는 액션
                    name: 'Add Data',
                    handler: (chart) =&amp;gt; {
                        const data = chart.data;
                        // 데이터셋이 있을 때만 실행
                        if (data.datasets.length &amp;gt; 0) {
                            // 레이블에 새로운 월 추가
                            data.labels = Utils.months({ count: data.labels.length + 1 });
                            // 각 데이터셋에 대해 새로운 랜덤 데이터 추가
                            data.datasets.forEach(dataset =&amp;gt; {
                                dataset.data.push(Utils.numbers({ count: 1, min: -100, max: 100 })[0]);
                            });
                            // 차트를 업데이트하여 시각적으로 반영
                            chart.update();
                        }
                    }
                },
                {
                    // 마지막 데이터셋을 제거하는 액션
                    name: 'Remove Dataset',
                    handler: (chart) =&amp;gt; {
                        // 데이터셋 리스트에서 마지막 데이터셋 제거
                        chart.data.datasets.pop();
                        // 차트를 업데이트하여 시각적으로 반영
                        chart.update();
                    }
                },
                {
                    // 마지막 데이터를 제거하는 액션
                    name: 'Remove Data',
                    handler: (chart) =&amp;gt; {
                        // 레이블에서 마지막 항목 제거
                        chart.data.labels.splice(-1, 1);
                        // 각 데이터셋에서 마지막 데이터 제거
                        chart.data.datasets.forEach(dataset =&amp;gt; {
                            dataset.data.pop();
                        });
                        // 차트를 업데이트하여 시각적으로 반영
                        chart.update();
                    }
                }
            ];

            const DATA_COUNT = 7;
            const NUMBER_CFG = { count: DATA_COUNT, min: -100, max: 100 };

            const labels = Utils.months({ count: DATA_COUNT });
            const data = {
                labels: labels,
                datasets: [
                    {
                        label: 'Dataset 1',
                        data: Utils.numbers(NUMBER_CFG),
                        borderColor: 'red',
                        backgroundColor: Utils.transparentize('red', 0.5),
                    },
                    {
                        label: 'Dataset 2',
                        data: Utils.numbers(NUMBER_CFG),
                        borderColor: 'blue',
                        backgroundColor: Utils.transparentize('blue', 0.5),
                    }
                ]
            };
            const config = {
                type: 'bar',
                data: data,
                options: {
                    responsive: true,
                    plugins: {
                        legend: {
                            position: 'top',
                        },
                        title: {
                            display: true,
                            text: 'Chart.js Bar Chart'
                        }
                    }
                },
            };

            const myChart = new Chart(
                document.getElementById('myChart'),
                config
            );

            actions.forEach(action =&amp;gt; {
                console.log(action);
                console.log(action.name.toLowerCase().replace(' ', ''));
                console.log(document.getElementById(action.name.toLowerCase().replace(' ', '')));

                document.getElementById(action.name.toLowerCase().replace(' ', '')).addEventListener('click', () =&amp;gt; action.handler(myChart));
            });
        });
    &amp;lt;/script&amp;gt;
&amp;lt;/body&amp;gt;

&amp;lt;/html&amp;gt;&quot;&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/chart.js&quot;&gt;&lt;/script&gt;
&lt;!-- Zoom 플러그인 --&gt;
&lt;script src=&quot;https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom&quot;&gt;&lt;/script&gt;
&lt;div style=&quot;width: 800px; height: 400px;&quot;&gt;&lt;!-- chart가 그려질 canvas를 생성 --&gt; &lt;canvas id=&quot;myChart&quot; width=&quot;800&quot; height=&quot;400&quot;&gt;&lt;/canvas&gt;&lt;/div&gt;
&lt;button id=&quot;randomize&quot;&gt;Randomize&lt;/button&gt; &lt;button id=&quot;adddataset&quot;&gt;Add Dataset&lt;/button&gt; &lt;button id=&quot;adddata&quot;&gt;Add Data&lt;/button&gt; &lt;button id=&quot;removedataset&quot;&gt;Remove Dataset&lt;/button&gt; &lt;button id=&quot;removedata&quot;&gt;Remove Data&lt;/button&gt;
&lt;script&gt;
        document.addEventListener('DOMContentLoaded', () =&gt; {
            const Utils = {
                numbers({ count, min, max }) {
                    return Array.from({ length: count }, () =&gt; Math.floor(Math.random() * (max - min + 1)) + min);
                },
                months({ count }) {
                    return Array.from({ length: count }, (_, i) =&gt; new Date(0, i).toLocaleString('default', { month: 'long' }));
                },
                namedColor(index) {
                    const colors = ['red', 'blue', 'green', 'yellow', 'orange', 'purple', 'cyan'];
                    return colors[index % colors.length];
                },
                transparentize(color, opacity) {
                    const rgb = color.replace(/rgba?/, '').replace(/[^\d,]/g, '').split(',').map(Number);
                    return `rgba(${rgb.join(',')}, ${opacity})`;
                }
            };


            const actions = [
                {
                    // 데이터의 값을 랜덤화하는 액션
                    name: 'Randomize',
                    handler: (chart) =&gt; {
                        // 각 데이터셋에 대해
                        chart.data.datasets.forEach(dataset =&gt; {
                            // 랜덤한 데이터 생성 (최소 -100, 최대 100)
                            dataset.data = Utils.numbers({ count: chart.data.labels.length, min: -100, max: 100 });
                        });
                        // 차트를 업데이트하여 시각적으로 반영
                        chart.update();
                    }
                },
                {
                    // 새로운 데이터셋을 추가하는 액션
                    name: 'Add Dataset',
                    handler: (chart) =&gt; {
                        const data = chart.data;
                        // 데이터셋 수에 따라 새로운 색상을 결정
                        const dsColor = Utils.namedColor(data.datasets.length);
                        const newDataset = {
                            // 새로운 데이터셋의 이름 설정
                            label: 'Dataset ' + (data.datasets.length + 1),
                            // 색상 설정 (투명하게)
                            backgroundColor: Utils.transparentize(dsColor, 0.5),
                            borderColor: dsColor,
                            borderWidth: 1,
                            // 랜덤 데이터 생성 (기존 레이블 수와 같은 수)
                            data: Utils.numbers({ count: data.labels.length, min: -100, max: 100 }),
                        };
                        // 데이터셋을 리스트에 추가
                        data.datasets.push(newDataset);
                        // 차트를 업데이트하여 시각적으로 반영
                        chart.update();
                    }
                },
                {
                    // 데이터에 새로운 값을 추가하는 액션
                    name: 'Add Data',
                    handler: (chart) =&gt; {
                        const data = chart.data;
                        // 데이터셋이 있을 때만 실행
                        if (data.datasets.length &gt; 0) {
                            // 레이블에 새로운 월 추가
                            data.labels = Utils.months({ count: data.labels.length + 1 });
                            // 각 데이터셋에 대해 새로운 랜덤 데이터 추가
                            data.datasets.forEach(dataset =&gt; {
                                dataset.data.push(Utils.numbers({ count: 1, min: -100, max: 100 })[0]);
                            });
                            // 차트를 업데이트하여 시각적으로 반영
                            chart.update();
                        }
                    }
                },
                {
                    // 마지막 데이터셋을 제거하는 액션
                    name: 'Remove Dataset',
                    handler: (chart) =&gt; {
                        // 데이터셋 리스트에서 마지막 데이터셋 제거
                        chart.data.datasets.pop();
                        // 차트를 업데이트하여 시각적으로 반영
                        chart.update();
                    }
                },
                {
                    // 마지막 데이터를 제거하는 액션
                    name: 'Remove Data',
                    handler: (chart) =&gt; {
                        // 레이블에서 마지막 항목 제거
                        chart.data.labels.splice(-1, 1);
                        // 각 데이터셋에서 마지막 데이터 제거
                        chart.data.datasets.forEach(dataset =&gt; {
                            dataset.data.pop();
                        });
                        // 차트를 업데이트하여 시각적으로 반영
                        chart.update();
                    }
                }
            ];

            const DATA_COUNT = 7;
            const NUMBER_CFG = { count: DATA_COUNT, min: -100, max: 100 };

            const labels = Utils.months({ count: DATA_COUNT });
            const data = {
                labels: labels,
                datasets: [
                    {
                        label: 'Dataset 1',
                        data: Utils.numbers(NUMBER_CFG),
                        borderColor: 'red',
                        backgroundColor: Utils.transparentize('red', 0.5),
                    },
                    {
                        label: 'Dataset 2',
                        data: Utils.numbers(NUMBER_CFG),
                        borderColor: 'blue',
                        backgroundColor: Utils.transparentize('blue', 0.5),
                    }
                ]
            };
            const config = {
                type: 'bar',
                data: data,
                options: {
                    responsive: true,
                    plugins: {
                        legend: {
                            position: 'top',
                        },
                        title: {
                            display: true,
                            text: 'Chart.js Bar Chart'
                        }
                    }
                },
            };

            const myChart = new Chart(
                document.getElementById('myChart'),
                config
            );

            actions.forEach(action =&gt; {
                console.log(action);
                console.log(action.name.toLowerCase().replace(' ', ''));
                console.log(document.getElementById(action.name.toLowerCase().replace(' ', '')));

                document.getElementById(action.name.toLowerCase().replace(' ', '')).addEventListener('click', () =&gt; action.handler(myChart));
            });
        });
    &lt;/script&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1666&quot; data-origin-height=&quot;946&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bt85fZ/btsLSqsFGsJ/fbwrRh0MTkN1XEzg03ZO61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bt85fZ/btsLSqsFGsJ/fbwrRh0MTkN1XEzg03ZO61/img.png&quot; data-alt=&quot;chart.js 이벤트 동작 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bt85fZ/btsLSqsFGsJ/fbwrRh0MTkN1XEzg03ZO61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbt85fZ%2FbtsLSqsFGsJ%2FfbwrRh0MTkN1XEzg03ZO61%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1666&quot; height=&quot;946&quot; data-origin-width=&quot;1666&quot; data-origin-height=&quot;946&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;chart.js 이벤트 동작 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;1. Randomize&lt;/h3&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;pre id=&quot;code_1737385013683&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; // 데이터의 값을 랜덤화하는 액션
{
    name: 'Randomize',
    handler: (chart) =&amp;gt; {
        // 각 데이터셋에 대해
        chart.data.datasets.forEach(dataset =&amp;gt; {
            // 랜덤한 데이터 생성 (최소 -100, 최대 100)
            dataset.data = Utils.numbers({ count: chart.data.labels.length, min: -100, max: 100 });
        });
        // 차트를 업데이트하여 시각적으로 반영
        chart.update();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;2. Add Dataset&lt;/h3&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;pre id=&quot;code_1737385086248&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
    // 새로운 데이터셋을 추가하는 액션
    name: 'Add Dataset',
    handler: (chart) =&amp;gt; {
        const data = chart.data;
        // 데이터셋 수에 따라 새로운 색상을 결정
        const dsColor = Utils.namedColor(data.datasets.length);
        const newDataset = {
            // 새로운 데이터셋의 이름 설정
            label: 'Dataset ' + (data.datasets.length + 1),
            // 색상 설정 (투명하게)
            backgroundColor: Utils.transparentize(dsColor, 0.5),
            borderColor: dsColor,
            borderWidth: 1,
            // 랜덤 데이터 생성 (기존 레이블 수와 같은 수)
            data: Utils.numbers({ count: data.labels.length, min: -100, max: 100 }),
        };
        // 데이터셋을 리스트에 추가
        data.datasets.push(newDataset);
        // 차트를 업데이트하여 시각적으로 반영
        chart.update();
    }
},&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;3. Add Data&lt;/h3&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;pre id=&quot;code_1737385115276&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
    // 데이터에 새로운 값을 추가하는 액션
    name: 'Add Data',
    handler: (chart) =&amp;gt; {
        const data = chart.data;
        // 데이터셋이 있을 때만 실행
        if (data.datasets.length &amp;gt; 0) {
            // 레이블에 새로운 월 추가
            data.labels = Utils.months({ count: data.labels.length + 1 });
            // 각 데이터셋에 대해 새로운 랜덤 데이터 추가
            data.datasets.forEach(dataset =&amp;gt; {
                dataset.data.push(Utils.numbers({ count: 1, min: -100, max: 100 })[0]);
            });
            // 차트를 업데이트하여 시각적으로 반영
            chart.update();
        }
    }
},&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;4. Remove Dataset&lt;/h3&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;pre id=&quot;code_1737385157391&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
    // 마지막 데이터셋을 제거하는 액션
    name: 'Remove Dataset',
    handler: (chart) =&amp;gt; {
        // 데이터셋 리스트에서 마지막 데이터셋 제거
        chart.data.datasets.pop();
        // 차트를 업데이트하여 시각적으로 반영
        chart.update();
    }
},&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;5. Remove Data&lt;/h3&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;pre id=&quot;code_1737385198708&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{
    // 마지막 데이터를 제거하는 액션
    name: 'Remove Data',
    handler: (chart) =&amp;gt; {
        chart.data.labels.splice(-1, 1); // 마지막 레이블 제거
        chart.data.datasets.forEach(dataset =&amp;gt; {
            dataset.data.pop(); // 각 데이터셋에서 마지막 데이터 제거
        });
        // 차트를 업데이트하여 삭제된 데이터를 반영
        chart.update();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;버튼 이벤트 연결하기&lt;/h3&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;각 버튼이 클릭되었을 때 해당하는 액션을 실행할 수 있도록 이벤트 리스너를 추가하는 부분입니다. 아래 코드는 actions 배열을 순회하여 각 액션에 대해 버튼을 설정하는 방법을 보여줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1737385270060&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;actions.forEach(action =&amp;gt; {
    // 각 액션을 콘솔에 출력하여 디버깅
    console.log(action);
    console.log(action.name.toLowerCase().replace(' ', '')); // 액션 이름을 소문자로 변환하고 공백을 제거
    console.log(document.getElementById(action.name.toLowerCase().replace(' ', ''))); // 버튼 요소 가져오기

    // 버튼에 클릭 이벤트 리스너 추가
    document.getElementById(action.name.toLowerCase().replace(' ', '')).addEventListener('click', () =&amp;gt; action.handler(myChart));
});&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_1737385322444&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script&amp;gt;
    document.addEventListener('DOMContentLoaded', () =&amp;gt; {
        const Utils = {
            numbers({ count, min, max }) {
                return Array.from({ length: count }, () =&amp;gt; Math.floor(Math.random() * (max - min + 1)) + min);
            },
            months({ count }) {
                return Array.from({ length: count }, (_, i) =&amp;gt; new Date(0, i).toLocaleString('default', { month: 'long' }));
            },
            namedColor(index) {
                const colors = ['red', 'blue', 'green', 'yellow', 'orange', 'purple', 'cyan'];
                return colors[index % colors.length];
            },
            transparentize(color, opacity) {
                const rgb = color.replace(/rgba?/, '').replace(/[^\d,]/g, '').split(',').map(Number);
                return `rgba(${rgb.join(',')}, ${opacity})`;
            }
        };


        const actions = [
            {
                // 데이터의 값을 랜덤화하는 액션
                name: 'Randomize',
                handler: (chart) =&amp;gt; {
                    // 각 데이터셋에 대해
                    chart.data.datasets.forEach(dataset =&amp;gt; {
                        // 랜덤한 데이터 생성 (최소 -100, 최대 100)
                        dataset.data = Utils.numbers({ count: chart.data.labels.length, min: -100, max: 100 });
                    });
                    // 차트를 업데이트하여 시각적으로 반영
                    chart.update();
                }
            },
            {
                // 새로운 데이터셋을 추가하는 액션
                name: 'Add Dataset',
                handler: (chart) =&amp;gt; {
                    const data = chart.data;
                    // 데이터셋 수에 따라 새로운 색상을 결정
                    const dsColor = Utils.namedColor(data.datasets.length);
                    const newDataset = {
                        // 새로운 데이터셋의 이름 설정
                        label: 'Dataset ' + (data.datasets.length + 1),
                        // 색상 설정 (투명하게)
                        backgroundColor: Utils.transparentize(dsColor, 0.5),
                        borderColor: dsColor,
                        borderWidth: 1,
                        // 랜덤 데이터 생성 (기존 레이블 수와 같은 수)
                        data: Utils.numbers({ count: data.labels.length, min: -100, max: 100 }),
                    };
                    // 데이터셋을 리스트에 추가
                    data.datasets.push(newDataset);
                    // 차트를 업데이트하여 시각적으로 반영
                    chart.update();
                }
            },
            {
                // 데이터에 새로운 값을 추가하는 액션
                name: 'Add Data',
                handler: (chart) =&amp;gt; {
                    const data = chart.data;
                    // 데이터셋이 있을 때만 실행
                    if (data.datasets.length &amp;gt; 0) {
                        // 레이블에 새로운 월 추가
                        data.labels = Utils.months({ count: data.labels.length + 1 });
                        // 각 데이터셋에 대해 새로운 랜덤 데이터 추가
                        data.datasets.forEach(dataset =&amp;gt; {
                            dataset.data.push(Utils.numbers({ count: 1, min: -100, max: 100 })[0]);
                        });
                        // 차트를 업데이트하여 시각적으로 반영
                        chart.update();
                    }
                }
            },
            {
                // 마지막 데이터셋을 제거하는 액션
                name: 'Remove Dataset',
                handler: (chart) =&amp;gt; {
                    // 데이터셋 리스트에서 마지막 데이터셋 제거
                    chart.data.datasets.pop();
                    // 차트를 업데이트하여 시각적으로 반영
                    chart.update();
                }
            },
            {
                // 마지막 데이터를 제거하는 액션
                name: 'Remove Data',
                handler: (chart) =&amp;gt; {
                    // 레이블에서 마지막 항목 제거
                    chart.data.labels.splice(-1, 1);
                    // 각 데이터셋에서 마지막 데이터 제거
                    chart.data.datasets.forEach(dataset =&amp;gt; {
                        dataset.data.pop();
                    });
                    // 차트를 업데이트하여 시각적으로 반영
                    chart.update();
                }
            }
        ];

        const DATA_COUNT = 7;
        const NUMBER_CFG = { count: DATA_COUNT, min: -100, max: 100 };

        const labels = Utils.months({ count: DATA_COUNT });
        const data = {
            labels: labels,
            datasets: [
                {
                    label: 'Dataset 1',
                    data: Utils.numbers(NUMBER_CFG),
                    borderColor: 'red',
                    backgroundColor: Utils.transparentize('red', 0.5),
                },
                {
                    label: 'Dataset 2',
                    data: Utils.numbers(NUMBER_CFG),
                    borderColor: 'blue',
                    backgroundColor: Utils.transparentize('blue', 0.5),
                }
            ]
        };
        const config = {
            type: 'bar',
            data: data,
            options: {
                responsive: true,
                plugins: {
                    legend: {
                        position: 'top',
                    },
                    title: {
                        display: true,
                        text: 'Chart.js Bar Chart'
                    }
                }
            },
        };

        const myChart = new Chart(
            document.getElementById('myChart'),
            config
        );

        actions.forEach(action =&amp;gt; {
            console.log(action);
            console.log(action.name.toLowerCase().replace(' ', ''));
            console.log(document.getElementById(action.name.toLowerCase().replace(' ', '')));

            document.getElementById(action.name.toLowerCase().replace(' ', '')).addEventListener('click', () =&amp;gt; action.handler(myChart));
        });
    });


&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;결론&lt;/h3&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;이 내용을 블로그에 포함시키면, Chart.js에서 버튼 이벤트를 어떻게 사용하는지에 대한 전반적인 이해를 돕는 데 큰 도움이 될 것입니다.&lt;/p&gt;</description>
      <category>개발/chart.js</category>
      <category>chart js tooltip custom</category>
      <category>chart.js tooltip</category>
      <category>chart.js tooltips</category>
      <category>chart.js 버튼 이벤트</category>
      <category>chart.js 이벤트</category>
      <category>chart.js 툴팁 옵션</category>
      <category>webcharts</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/117</guid>
      <comments>https://nicksoon.tistory.com/entry/chartjs-%EB%B2%84%ED%8A%BC-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%98%88%EC%A0%9C#entry117comment</comments>
      <pubDate>Mon, 20 Jan 2025 23:47:32 +0900</pubDate>
    </item>
    <item>
      <title>Chart.js에서 Zoom 플러그인을 활용한 효과적인 데이터 시각화</title>
      <link>https://nicksoon.tistory.com/entry/Chartjs%EC%97%90%EC%84%9C-Zoom-%ED%94%8C%EB%9F%AC%EA%B7%B8%EC%9D%B8%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%9A%A8%EA%B3%BC%EC%A0%81%EC%9D%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%8B%9C%EA%B0%81%ED%99%94</link>
      <description>&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;&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;사용자에게 값에 따라 추가하는 기능과 마우스로 할 수 있는 방법을 선택해 제공을 한다면 더욱 사용자 친화적인 기능일 수 있어요&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://nickdeveloper.co.kr/entry/Chartjs에서-MinMax를-활용한-Zoom-InOut-기능-구현하기&quot;&gt;https://nickdeveloper.co.kr/entry/Chartjs에서-MinMax를-활용한-Zoom-InOut-기능-구현하기&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1736780253835&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;Chart.js에서 Min/Max를 활용한 Zoom In/Out 기능 구현하기&quot; data-og-description=&quot;이번 포스트에서는 Chart.js의 min/max 설정을 활용하여 차트에서 Zoom In/Out 기능을 구현하는 방법을 자세히 다룰 것입니다. 이 기능은 사용자가 차트의 특정 부분을 더 자세히 보거나, 전체적인 관점&quot; data-og-host=&quot;nickdeveloper.co.kr&quot; data-og-source-url=&quot;https://nickdeveloper.co.kr/entry/Chartjs에서-MinMax를-활용한-Zoom-InOut-기능-구현하기&quot; data-og-url=&quot;https://nickdeveloper.co.kr/entry/Chartjs%EC%97%90%EC%84%9C-MinMax%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-Zoom-InOut-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b1tKrw/hyX0uaOsFW/11VKTKlIdkJi21lU3zPN0k/img.png?width=800&amp;amp;height=386&amp;amp;face=0_0_800_386,https://scrap.kakaocdn.net/dn/gHbEt/hyX0xyzTDo/0G9zu6NiOyhykYNn2LPTMK/img.png?width=800&amp;amp;height=386&amp;amp;face=0_0_800_386,https://scrap.kakaocdn.net/dn/1zdLU/hyX0rkOkl1/ggQ4Ok2siNMxZJNvgCzWXk/img.png?width=1642&amp;amp;height=1118&amp;amp;face=0_0_1642_1118&quot;&gt;&lt;a href=&quot;https://nickdeveloper.co.kr/entry/Chartjs에서-MinMax를-활용한-Zoom-InOut-기능-구현하기&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://nickdeveloper.co.kr/entry/Chartjs에서-MinMax를-활용한-Zoom-InOut-기능-구현하기&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b1tKrw/hyX0uaOsFW/11VKTKlIdkJi21lU3zPN0k/img.png?width=800&amp;amp;height=386&amp;amp;face=0_0_800_386,https://scrap.kakaocdn.net/dn/gHbEt/hyX0xyzTDo/0G9zu6NiOyhykYNn2LPTMK/img.png?width=800&amp;amp;height=386&amp;amp;face=0_0_800_386,https://scrap.kakaocdn.net/dn/1zdLU/hyX0rkOkl1/ggQ4Ok2siNMxZJNvgCzWXk/img.png?width=1642&amp;amp;height=1118&amp;amp;face=0_0_1642_1118');&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;Chart.js에서 Min/Max를 활용한 Zoom In/Out 기능 구현하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번 포스트에서는 Chart.js의 min/max 설정을 활용하여 차트에서 Zoom In/Out 기능을 구현하는 방법을 자세히 다룰 것입니다. 이 기능은 사용자가 차트의 특정 부분을 더 자세히 보거나, 전체적인 관점&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;nickdeveloper.co.kr&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;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;데이터 시각화에 있어 사용자 상호작용은 매우 중요한 요소입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;특히 대량의 데이터를 다룰 때, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; 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;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이번 포스트에서는 Chart.js 라이브러리와 Zoom 플러그인을 사용하여 &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;&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;2524&quot; data-origin-height=&quot;1336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzupjk/btsLMlYdHCe/LWJoaMprsIpjDEmsCI0Fk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzupjk/btsLMlYdHCe/LWJoaMprsIpjDEmsCI0Fk1/img.png&quot; data-alt=&quot;chart.js 이미지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzupjk/btsLMlYdHCe/LWJoaMprsIpjDEmsCI0Fk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbzupjk%2FbtsLMlYdHCe%2FLWJoaMprsIpjDEmsCI0Fk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2524&quot; height=&quot;1336&quot; data-origin-width=&quot;2524&quot; data-origin-height=&quot;1336&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;chart.js 이미지&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 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;1. 필요한 라이브러리 설정&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;먼저, Chart.js와 Zoom 플러그인, 그리고 터치 이벤트 지원을 위한 Hammer.js를 프로젝트에 포함시켜야 합니다.&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;CDN을 통해 이를 쉽게 구현할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1736779589366&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;script src=&quot;https://cdn.jsdelivr.net/npm/chart.js&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&quot;https://cdn.jsdelivr.net/npm/hammerjs@2.0.8&quot;&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script src=&quot;https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&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;path/to/...&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;)은 &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;404 오류를 발생시킬 수 있으므로, CDN 링크를 사용하는 것이 안전합니다.&lt;/span&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;size18&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;HTML에 차트를 그릴 캔버스 요소를 추가합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1736779657938&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;canvas id=&quot;myChart&quot;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;/code&gt;&lt;/pre&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;size18&quot;&gt;3. 차트 초기화 및 Zoom 설정&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;JavaScript를 사용하여 차트를 초기화하고 Zoom 옵션을 구성합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1736779692155&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;onst ctx = document.getElementById('myChart').getContext('2d');
const config = {
    type: 'line',
    data: {
        labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
        datasets: [{
            label: 'My First Dataset',
            data: [65, 59, 80, 81, 56, 55, 40],
            fill: false,
            borderColor: 'rgb(75, 192, 192)',
            tension: 0.1
        }]
    },
    options: {
        plugins: {
            zoom: {
                zoom: {
                    wheel: {
                        enabled: true,
                    },
                    pinch: {
                        enabled: true
                    },
                    mode: 'xy',
                }
            }
        }
    }
};
let myChart = new Chart(ctx, config);&lt;/code&gt;&lt;/pre&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;size18&quot;&gt;4. Zoom 옵션 설명&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 style=&quot;color: #000000;&quot;&gt;wheel.enabled: 마우스 휠을 사용한 줌 기능을 활성화합니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;pinch.enabled: 터치 디바이스에서 핀치 줌 기능을 활성화합니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;mode: 줌 방향을 설정합니다. 'xy'는 가로세로 모두, 'x'는 가로만, 'y'는 세로만 줌이 가능합니다.&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;3344&quot; data-origin-height=&quot;1728&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pcHdL/btsLKKLJ3Yb/62cRZH0ZMZ3P2c0w84XB51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pcHdL/btsLKKLJ3Yb/62cRZH0ZMZ3P2c0w84XB51/img.png&quot; data-alt=&quot;줌 확대 된 내용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pcHdL/btsLKKLJ3Yb/62cRZH0ZMZ3P2c0w84XB51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpcHdL%2FbtsLKKLJ3Yb%2F62cRZH0ZMZ3P2c0w84XB51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3344&quot; height=&quot;1728&quot; data-origin-width=&quot;3344&quot; data-origin-height=&quot;1728&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;줌 확대 된 내용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;5. 추가 고려사항&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 style=&quot;color: #000000;&quot;&gt;성능 최적화: 대&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;량의 데이터를 다룰 때는 성능 최적화를 고려해야 합니다. 데이터 샘플링이나 지연 로딩 기법을 활용할 수 있습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;반응형 디자인: Chart.js는 기본적으로 반응형을 지원하지만, 컨테이너 크기 변경 시 차트가 올바르게 조정되는지 확인해야 합니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;사용자 경험(UX) 개선: 줌 기능 사용법을 사용자에게 안내하는 툴팁이나 도움말을 추가하면 좋습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;6. Pan 기능 추가&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;줌 외에도 Pan(이동) 기능을 추가하여 사용자 경험을 더욱 향상시킬 수 있습니다. 옵션에 다음과 같이 추가합니다:&lt;/p&gt;
&lt;pre id=&quot;code_1736781326703&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;options: {
	plugins: {
		zoom: {
			zoom: {
				wheel: {
					enabled: true,
				},
				pinch: {
					enabled: true
				},
				mode: 'xy',
            },
			pan: {
				enabled: true,
				mode: 'xy',
			}
		}
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;7.리셋 버튼 구현&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;pre id=&quot;code_1736780010810&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;button onclick=&quot;resetZoom()&quot;&amp;gt;Reset Zoom&amp;lt;/button&amp;gt;
&amp;lt;script&amp;gt;
function resetZoom() {
    myChart.resetZoom();
}
&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 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&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;Chart.js와 Zoom 플러그인을 활용하면 사용자 친화적이고 인터랙티브한 데이터 시각화를 쉽게 구현할 수 있습니다.&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;사용자의 요구사항과 데이터의 특성에 맞게 줌과 팬 옵션을 조정하고, 필요에 따라 추가 기능을 구현하면 더욱 강력한 데이터 시각화 도구를 만들 수 있습니다. 또한, 성능 최적화와 사용자 경험 개선에 지속적인 관심을 기울이는 것이 중요합니다.&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;Chart.js의 Zoom 플러그인은 지속적으로 업데이트되고 있으므로, 최신 버전의 문서를 참조하여 새로운 기능이나 변경사항을 확인하는 것이 좋습니다. 데이터 시각화의 세계는 끊임없이 발전하고 있으며, 이러한 도&lt;/p&gt;</description>
      <category>개발/chart.js</category>
      <category>chart.js zoominout</category>
      <category>chart.js 플러그인</category>
      <category>chartjs</category>
      <category>Chartjs zoom example</category>
      <category>chartjs-plugin-zoom cdn</category>
      <category>interactivecharts</category>
      <category>zoom in</category>
      <category>zoom out</category>
      <category>zoom 플러그인</category>
      <category>zoomplugin</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/116</guid>
      <comments>https://nicksoon.tistory.com/entry/Chartjs%EC%97%90%EC%84%9C-Zoom-%ED%94%8C%EB%9F%AC%EA%B7%B8%EC%9D%B8%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%ED%9A%A8%EA%B3%BC%EC%A0%81%EC%9D%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%8B%9C%EA%B0%81%ED%99%94#entry116comment</comments>
      <pubDate>Tue, 14 Jan 2025 00:00:54 +0900</pubDate>
    </item>
    <item>
      <title>네이버 API  (Authentication failed error code 024) 트러블 슈팅</title>
      <link>https://nicksoon.tistory.com/entry/%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%94%94%EB%B2%A8%EB%A1%AD-API-%EA%B0%80%EC%A0%B8%EC%98%A4%EB%A9%B4%EC%84%9C-%EC%97%90%EB%9F%AC-%EB%B0%9C%EC%83%9D-Authentication-failed</link>
      <description>&lt;center&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8542284842011502&quot;&gt;&lt;/script&gt;
&lt;!-- 닉순 디스플레이 광고 반응형 --&gt;&lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: block;&quot; data-ad-client=&quot;ca-pub-8542284842011502&quot; data-ad-slot=&quot;3598841997&quot; data-ad-format=&quot;auto&quot; data-full-width-responsive=&quot;false&quot;&gt;&lt;/ins&gt;
&lt;script&gt;     (adsbygoogle = window.adsbygoogle || []).push({});&lt;/script&gt;
&lt;/center&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f8f8f8; color: #1d1c1d; text-align: left;&quot;&gt;Error 내용:{&quot;errorMessage&quot;:&quot;Scope Status Invalid : Authentication failed. (인증에 실패했습니다.)&quot;,&quot;errorCode&quot;:&quot;024&quot;}&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 style=&quot;background-color: #f8f8f8; color: #1d1c1d; text-align: left;&quot;&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;pre id=&quot;code_1736755948865&quot; class=&quot;cos&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;php&quot;&gt;&lt;code&gt;    $category = new Category($open_api1[0],$open_api1[1]);
    
    // 기기별
    $url = &quot;https://openapi.naver.com/v1/datalab/shopping/category/device&quot;;
    $result1 =  $category-&amp;gt;GET($url,&quot;\&quot;$number\&quot;&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이렇게 코드를 만들었는데&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1736755948866&quot; class=&quot;subunit&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;Error 내용:{&quot;errorMessage&quot;:&quot;Scope Status Invalid : Authentication failed. (인증에 실패했습니다.)&quot;,&quot;errorCode&quot;:&quot;024&quot;}&lt;/code&gt;&lt;/pre&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;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;다른 API 키를 확인을 해 보았더니 잘 나왔습니다.&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;span style=&quot;background-color: #fafafa; color: #323232; text-align: left;&quot;&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 style=&quot;background-color: #fafafa; color: #323232; text-align: left;&quot;&gt;&lt;a href=&quot;https://developers.naver.com/apps/#/list&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://developers.naver.com/apps/#/list&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1736756938436&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;애플리케이션 - NAVER Developers&quot; data-og-description=&quot;&quot; data-og-host=&quot;developers.naver.com&quot; data-og-source-url=&quot;https://developers.naver.com/apps/#/list&quot; data-og-url=&quot;https://developers.naver.com/apps/#/list&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://developers.naver.com/apps/#/list&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developers.naver.com/apps/#/list&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&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;애플리케이션 - NAVER Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developers.naver.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 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 style=&quot;color: #777777; text-align: center;&quot;&gt;1. Application에 내 &lt;span style=&quot;color: #777777; text-align: center;&quot;&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;1221&quot; data-origin-height=&quot;243&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cH12Me/btsLLNOecuQ/mUScbcdkkgIm6W8iUrZjQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cH12Me/btsLLNOecuQ/mUScbcdkkgIm6W8iUrZjQK/img.png&quot; data-alt=&quot;네이버 디벨로퍼 Application 탭&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cH12Me/btsLLNOecuQ/mUScbcdkkgIm6W8iUrZjQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcH12Me%2FbtsLLNOecuQ%2FmUScbcdkkgIm6W8iUrZjQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1221&quot; height=&quot;243&quot; data-origin-width=&quot;1221&quot; data-origin-height=&quot;243&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;네이버 디벨로퍼 Application 탭&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 data-ke-size=&quot;size16&quot;&gt;2. API 리스트에서 API 선택&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;932&quot; data-origin-height=&quot;703&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHLngI/btsLMJEp0re/kHs3WD7ybMxiFHSPMEfSrK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHLngI/btsLMJEp0re/kHs3WD7ybMxiFHSPMEfSrK/img.png&quot; data-alt=&quot;애플리케이션 리스트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHLngI/btsLMJEp0re/kHs3WD7ybMxiFHSPMEfSrK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHLngI%2FbtsLMJEp0re%2FkHs3WD7ybMxiFHSPMEfSrK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;932&quot; height=&quot;703&quot; data-origin-width=&quot;932&quot; data-origin-height=&quot;703&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;애플리케이션 리스트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. API 설정 클릭&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;124&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q3frc/btsLKrk6iL7/KX4JDFeZn9O3uphfRKnmy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q3frc/btsLKrk6iL7/KX4JDFeZn9O3uphfRKnmy1/img.png&quot; data-alt=&quot;네이버 디벨로퍼스 내 애플리케이션 API설정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q3frc/btsLKrk6iL7/KX4JDFeZn9O3uphfRKnmy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq3frc%2FbtsLKrk6iL7%2FKX4JDFeZn9O3uphfRKnmy1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;905&quot; height=&quot;124&quot; data-origin-width=&quot;905&quot; data-origin-height=&quot;124&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;네이버 디벨로퍼스 내 애플리케이션 API설정&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;4. 사용 API에 필요한 기능 추가&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;854&quot; data-origin-height=&quot;700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcuLeQ/btsLKKxZ4EF/SKknvhDaQ6YAk6TpmhE4ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcuLeQ/btsLKKxZ4EF/SKknvhDaQ6YAk6TpmhE4ak/img.png&quot; data-alt=&quot;애플리케이션 추가 하기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcuLeQ/btsLKKxZ4EF/SKknvhDaQ6YAk6TpmhE4ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcuLeQ%2FbtsLKKxZ4EF%2FSKknvhDaQ6YAk6TpmhE4ak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;854&quot; height=&quot;700&quot; data-origin-width=&quot;854&quot; data-origin-height=&quot;700&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;애플리케이션 추가 하기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 이렇게 추가를 했습니다. 데이터렙(쇼핑인사이트)&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;887&quot; data-origin-height=&quot;797&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6Amba/btsLLVexh6f/wVXnaglboj6jvkfVghQ120/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6Amba/btsLLVexh6f/wVXnaglboj6jvkfVghQ120/img.png&quot; data-alt=&quot;네이버 디벨로퍼 네 애플리케이션 정보&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6Amba/btsLLVexh6f/wVXnaglboj6jvkfVghQ120/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6Amba%2FbtsLLVexh6f%2FwVXnaglboj6jvkfVghQ120%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;797&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;797&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;네이버 디벨로퍼 네 애플리케이션 정보&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 추가를 하고 에러가 사라졌습니다&amp;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;개발 전 혹은 서비스 배포 전 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;</description>
      <category>개발/개발 필기</category>
      <category>api 설정</category>
      <category>authentication failed</category>
      <category>errorcode:024</category>
      <category>ErrorMessage</category>
      <category>naver developers</category>
      <category>Naver Open API</category>
      <category>네이버 api 24error</category>
      <category>네이버 디벨로퍼</category>
      <category>네이버 오픈 API</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/115</guid>
      <comments>https://nicksoon.tistory.com/entry/%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%94%94%EB%B2%A8%EB%A1%AD-API-%EA%B0%80%EC%A0%B8%EC%98%A4%EB%A9%B4%EC%84%9C-%EC%97%90%EB%9F%AC-%EB%B0%9C%EC%83%9D-Authentication-failed#entry115comment</comments>
      <pubDate>Mon, 13 Jan 2025 17:23:00 +0900</pubDate>
    </item>
    <item>
      <title>JSON Error: Single unpaired UTF-16 surrogate in unicode escape</title>
      <link>https://nicksoon.tistory.com/entry/JSON-Error-Single-unpaired-UTF-16-surrogate-in-unicode-escape</link>
      <description>&lt;h3 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;PHP에서 JSON 데이터 처리: 나의 3시간을 날려버린 오류와 해결책&lt;/h3&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;&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;최근에 PHP로 개발하면서 JSON 데이터를 배열로 변환하려고 할 때, &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;&quot;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Single unpaired UTF-16 surrogate in unicode escape&lt;/b&gt;&lt;/span&gt;&quot; 오류에 부딪혔습니다. &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;이 오류는 작은 문제 같지만 결국 저를 괴롭히며 소중한 3시간을 날려버렸습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;JSON 데이터 디코딩의 기본&lt;/h4&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;JSON 문자열을 배열로 변환할 때, 우리는 흔히 다음과 같은 코드를 사용합니다:&lt;/p&gt;
&lt;pre id=&quot;code_1736483072423&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$arrayData = json_decode($jsonData,true);&lt;/code&gt;&lt;/pre&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;&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1736483119786&quot; class=&quot;php&quot; data-ke-language=&quot;php&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$arrayData = json_decode($jsonData,true);
if (json_last_error() !== JSON_ERROR_NONE) {
    echo 'JSON Error: ' . json_last_error_msg(); // 에러 메시지 출력
}&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;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;제 경우, 출력된 오류 메시지는 다음과 같았습니다:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1736484794686&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;JSON Error: Single unpaired UTF-16 surrogate in unicode escape&lt;/code&gt;&lt;/pre&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;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;오류의 원인&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;불완전한 UTF-16 서로게이트 쌍&lt;/b&gt;&lt;br /&gt;UTF-16 인코딩에서 특정 문자는 두 개의 16비트 코드 유닛(서로게이트 쌍)으로 표현됩니다. 하나가 결여될 경우, 이 오류가 발생할 수 있습니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;귀여운 이모지 사용&lt;/b&gt;&lt;br /&gt;다음과 같은 귀여운 이모지가 포함된 데이터를 수신했을 때도 문제가 발생했습니다:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1736483230954&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;...[
	{
    	&quot;categoryId&quot;:&quot;aa95b614cf7646169421427cae6459b1&quot;,
        &quot;title&quot;:&quot; 곱이곱다&quot;,
        &quot;displayCount&quot;:12,
        &quot;categoryType&quot;:&quot;DISPLAY&quot;
    },
    {
    	&quot;categoryId&quot;:&quot;1f6e1a2f75bf4003903a6feccd489f5f&quot;,
        &quot;title&quot;:&quot; 내일도착보장 &quot;,
        &quot;displayCount&quot;:12,
        &quot;categoryType&quot;:&quot;DISPLAY&quot;
    },
    {
    	&quot;categoryId&quot;:&quot;b9f162e5fc464bf0a1dd8f70cac52d1e&quot;,
        &quot;title&quot;:&quot; 무료배송 ️&quot;,
        &quot;displayCount&quot;:12,
        &quot;categoryType&quot;:&quot;DISPLAY&quot;
    },
     ...&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이러한 이모지는 JSON 데이터의 파싱을 방해했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;해결 방법&lt;/h4&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;1. 이모지를 제거해 줍니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;이모지를 사라지게 하기 위해 다음과 같은 정규 표현식을 사용할 수 있습니다:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1736484465863&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$cleaned_data = pregReplace('/[\x{1F000}-\x{1FFFF}]|[\x{2600}-\x{27BF}]|[\x{1F900}-\x{1F9FF}]/u', '', $jsonData);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2.잘못된 유니코드 이스케이프 시퀀스 제거&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: left;&quot;&gt;불완전한 Unicode 이스케이프 시퀀스를 제거하는 방법은 다음과 같습니다:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1736484539752&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;$cleanedData = preg_replace('/\\\\u[dD][89abAB][0-9a-fA-F]{2}(?!\\\\u[dD][c-fC-F][0-9a-fA-F]{2})/', '', $cleanedData);&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;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이 두 스텝을 다음과 같이 결합하여 최종 코드를 작성했습니다:&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1736484634409&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 이모지를 제거해 줍니다.
$cleanedData = preg_replace('/[\x{1F000}-\x{1FFFF}]|[\x{2600}-\x{27BF}]|[\x{1F900}-\x{1F9FF}]/u', '', $jsonData); 
// 잘못된 유니코드 이스케이프 시퀀스 제거:
$cleanedData = preg_replace('/\\\\u[dD][89abAB][0-9a-fA-F]{2}(?!\\\\u[dD][c-fC-F][0-9a-fA-F]{2})/', '', $cleanedData); 

// 디코딩
$arrayData = json_decode($cleanedData,true);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이렇게 하면 JSON 데이터를 문제 없이 배열로 변환할 수 있었습니다.&lt;/span&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;이러한 경험이 다른 개발자에게도 도움이 되기를 바랍니다!&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;/p&gt;
&lt;p data-ke-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>
      <category>JSON</category>
      <category>json error</category>
      <category>php</category>
      <category>unicode escape</category>
      <category>utf-16</category>
      <category>UTF16</category>
      <category>디버깅</category>
      <category>이모지</category>
      <category>정규표현식</category>
      <category>프로그래밍</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/114</guid>
      <comments>https://nicksoon.tistory.com/entry/JSON-Error-Single-unpaired-UTF-16-surrogate-in-unicode-escape#entry114comment</comments>
      <pubDate>Fri, 10 Jan 2025 13:57:36 +0900</pubDate>
    </item>
    <item>
      <title>효율적인 JSON 저장을 위한 데이터베이스 정규형 이해하기</title>
      <link>https://nicksoon.tistory.com/entry/%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9D%B8-JSON-%EC%A0%80%EC%9E%A5%EC%9D%84-%EC%9C%84%ED%95%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%A0%95%EA%B7%9C%ED%98%95-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</link>
      <description>&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;&lt;/p&gt;
&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;TINYTEXT, TEXT, MEDIUMTEXT, LONGTEXT와 같이 &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;&lt;/p&gt;
&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;&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;&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;style5&quot; /&gt;
&lt;p style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;텍스트 타입의 구분:&lt;/b&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 style=&quot;color: #000000;&quot;&gt;&lt;b&gt;TINYTEXT:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;최대 256바이트의 작은 데이터에 적합합니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;TEXT:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;65,535바이트, 주로 일반적인 텍스트 정보에 사용됩니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MEDIUMTEXT:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;16MB까지 허용되며, 대량의 텍스트 데이터를 저장할 수 있습니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;LONGTEXT:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;무려 4GB까지 저장 가능하여, 대량의 문서나 긴 문자열을 효과적으로 관리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&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;저의 경험을 통해 한 가지 흥미로운 사례를 공유하고자 합니다. &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;처음에는 JSON 형식의 데이터를 TEXT 타입으로 저장했습니다. &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;&lt;/p&gt;
&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;길이가 긴 JSON 데이터는 중간에 잘려버리는 일이 발생한 것입니다. &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;그렇게 결국 MEDIUMTEXT로 변경했더니, 데이터는 모두 안정적으로 저장되었습니다. &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;처음에는 50개, 100개, 200개 정도의 데이터까지는 별 문제가 없었습니다. &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;&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;b&gt;예상 원인:&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal; background-color: #ffffff; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;메모리 사용:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;데이터가 많은 경우, 메모리의 부담이 커져 성능 저하를 초래합니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;I/O 작업:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;디스크에서 데이터를 읽고 쓰는 속도가 느려지면 전체 애플리케이션의 반응성이 떨어집니다.&lt;/li&gt;
&lt;li style=&quot;color: #000000;&quot;&gt;&lt;b&gt;네트워크 대역폭:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&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;&lt;span style=&quot;background-color: #ffffff; color: #000000; 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;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;그 결과, 저장하고자 했던 JSON 데이터들이 무겁게 느껴지기 시작했고,&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;&lt;/p&gt;
&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;속도를 유지하기 위해, 필수적인 데이터만 나누어 저장하고 기존의 MEDIUMTEXT 타입 사용도 고려했습니다.&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;b&gt;마냥 간단하게 처리하려고 할 경우에 큰 문제에 직면할 수 있다&lt;/b&gt;'는 것이었습니다. &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; 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;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이뿐만 아니라, 이 과정은 정규형에 대해 다시 고민하게 해주었습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;데이터베이스 설계의 원칙인 정규형(Normalization)은 데이터의 중복을 최소화하고 무결성을 유지하는 데 중요한 역할을 합니다. &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;&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;&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;&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;&lt;/p&gt;
&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;&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;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;적절한 저장 방식을 선택하고, &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000; 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;&lt;span style=&quot;background-color: #ffffff; color: #000000; text-align: start;&quot;&gt;이처럼 우리는 데이터의 크기뿐 아니라, 그 성능과 효율성을 모두 고려해야만 성공적인 데이터베이스 관리를 할 수 있습니다. &lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>JSON</category>
      <category>mediumtext</category>
      <category>데이터관리</category>
      <category>데이터베이스</category>
      <category>데이터베이스설계</category>
      <category>성능최적화</category>
      <category>텍스트저장</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/113</guid>
      <comments>https://nicksoon.tistory.com/entry/%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9D%B8-JSON-%EC%A0%80%EC%9E%A5%EC%9D%84-%EC%9C%84%ED%95%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%A0%95%EA%B7%9C%ED%98%95-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0#entry113comment</comments>
      <pubDate>Thu, 9 Jan 2025 09:57:27 +0900</pubDate>
    </item>
    <item>
      <title>Turbopack란?</title>
      <link>https://nicksoon.tistory.com/entry/Turbopack%EB%9E%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 next.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;Turbopack이란? 갑자기 설치를 하면 좋을 것 같은 이름이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 아무것도 모르고 설치를 해야 하나? 괜히 ESline 에 걸려 에러만 나는 것은 아닌지 찾아봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Turbopack는 JavaScript와 TypeScript에 최적화된 점진적 번들러로, Rust로 작성되었으며 Next.js에 내장되어 있다&lt;span style=&quot;background-color: #111111; color: #e2e8f0; 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;점진적 번들러? Rust로 작성? Next에 내장? webpack의 후속작?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 알 수 없는 말을이 있을 겁니다. 이걸 다 설명하기는 너무 루즈하고 Vite와 비슷한데 성능이 우수하다고 생가하면 되는데요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 Vite가 무엇인지 모를 수도 있고요&amp;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;이전에는 Vite를 사용했지만 next에서는 베타로 turbopack을 제공을 하게 된 것입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Turbopack의 주요 특징&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;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존 Webpack, Vite보다 훨씬 빠른 성능.&lt;/li&gt;
&lt;li&gt;Rust로 구현되어 CPU 및 메모리 효율이 높음.&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;Hot Module Replacement (HMR)&lt;/b&gt; 지원.&lt;/li&gt;
&lt;li&gt;대규모 프로젝트에서도 빌드 속도가 매우 빠름.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Incremental Compilation (증분 컴파일)&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;완벽한 Next.js 통합&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Next.js에 최적화된 설정을 제공.&lt;/li&gt;
&lt;li&gt;pages/와 app/ 디렉토리 모두 지원.&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;Turbopack은 Next.js 외에도 다양한 JavaScript 프레임워크에서 사용될 가능성이 높음.&lt;/li&gt;
&lt;li&gt;Vercel은 이를 Webpack처럼 널리 사용되는 번들러로 발전시키는 것을 목표로 함.&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Turbopack vs Webpack vs Vite&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특징TurbopackWebpackVite&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;b&gt;특징&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Turbopack&lt;/td&gt;
&lt;td&gt;Webpack&lt;/td&gt;
&lt;td&gt;Vite&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;기술 기반&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Rust&lt;/td&gt;
&lt;td&gt;JavaScript&lt;/td&gt;
&lt;td&gt;JavaScript&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;속도&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;매우 빠름&lt;/td&gt;
&lt;td&gt;느림&lt;/td&gt;
&lt;td&gt;빠름&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;사용성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Next.js에 최적화&lt;/td&gt;
&lt;td&gt;범용&lt;/td&gt;
&lt;td&gt;범용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Hot Reloading&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;빠르고 효율적&lt;/td&gt;
&lt;td&gt;느림&lt;/td&gt;
&lt;td&gt;빠르고 효율적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;빌드 최적화&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Incremental Compilation&lt;/td&gt;
&lt;td&gt;Full Bundling&lt;/td&gt;
&lt;td&gt;Pre-bundling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;확장성&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;초기 단계&lt;/td&gt;
&lt;td&gt;매우 널리 사용됨&lt;/td&gt;
&lt;td&gt;상대적으로 적은 도입률&lt;/td&gt;
&lt;/tr&gt;
&lt;/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;이런 내용이 있더라고요 하 빠르구나 그럼 사용해야지 하고 사용하기로 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1735632065484&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; &quot;scripts&quot;: {
    &quot;dev&quot;: &quot;next dev --turbopack&quot;,
    &quot;build&quot;: &quot;next build&quot;,
    &quot;start&quot;: &quot;next start&quot;,
    &quot;build-start&quot;: &quot;next build &amp;amp;&amp;amp; next start&quot;,
    &quot;lint&quot;: &quot;next lint&quot;,
    &quot;watch&quot;: &quot;nodemon&quot;
  },&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 사용하기로 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>NeXT</category>
      <category>Turbopack</category>
      <category>프론트엔드</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/112</guid>
      <comments>https://nicksoon.tistory.com/entry/Turbopack%EB%9E%80#entry112comment</comments>
      <pubDate>Tue, 31 Dec 2024 16:59:38 +0900</pubDate>
    </item>
    <item>
      <title>next 폴더 src 그리고 import alias</title>
      <link>https://nicksoon.tistory.com/entry/next-%ED%8F%B4%EB%8D%94-src-%EA%B7%B8%EB%A6%AC%EA%B3%A0-import-alias</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;next를 설치하다 보니 src를 사용할 거니?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;import alias를 사용할 거니?&amp;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;src에 담아서 개발을해? import alias는 '@/~' 을 사용한다고 ? 당연하지 라고 생각을 했어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 왜 당연할까요? 또 import alias는 기본 no로 되어 있어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭐 관리가 쉬워지고 import 코드가 깔끔해져서 그러긴 한데요 좀더 찾아봤어요&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;src/ 디렉토리를 사용하는 장점&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;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 소스 코드 파일을 src/ 디렉토리 아래로 정리하여 루트 디렉토리가 깔끔해집니다.&lt;/li&gt;
&lt;li&gt;루트 디렉토리에는 설정 파일(예: package.json, next.config.js)만 남고, 소스 코드와 명확히 분리됩니다.&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;프로젝트가 커질수록 디렉토리가 많아지는데, src/ 디렉토리를 사용하면 구조적인 명확성을 유지할 수 있습니다.&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;src/ 아래에 pages/, components/, utils/, api/ 등을 세분화하여 각 역할에 맞는 파일을 쉽게 찾을 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1735630267870&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;project-root/
├── public/                # 정적 파일
├── src/                   # 소스 코드
│   ├── pages/             # Next.js의 라우팅 파일
│   ├── components/        # 재사용 가능한 컴포넌트
│   ├── styles/            # 전역 및 모듈 CSS
│   ├── hooks/             # 커스텀 React Hook
│   ├── utils/             # 유틸리티 함수
│   ├── context/           # React Context API 파일
│   └── api/               # API 호출 로직
├── .eslintrc.json         # ESLint 설정 파일
├── next.config.js         # Next.js 설정 파일
├── package.json           # npm 의존성 관리
└── README.md              # 프로젝트 설명&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Import Alias란?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Import Alias&lt;/b&gt;는 상대 경로 대신 &lt;b&gt;짧고 명확한 경로&lt;/b&gt;를 사용하여 파일을 가져올 수 있도록 설정하는 것입니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;예시: Import Alias 없이&lt;/b&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1735630349563&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import Header from &quot;../../components/Header&quot;; 
import Footer from &quot;../../components/shared/Footer&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;예시: Import Alias 사용&lt;/b&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;javascript&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;&lt;span data-state=&quot;closed&quot;&gt;코드 복사&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;script src=&quot;https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8542284842011502&quot;&gt;&lt;/script&gt;
&lt;!-- 닉순 고정 디스플레이 고정형 320x250 --&gt; &lt;ins class=&quot;adsbygoogle&quot; style=&quot;display: inline-block; width: 300px; height: 250px;&quot; data-ad-client=&quot;ca-pub-8542284842011502&quot; data-ad-slot=&quot;1881030676&quot;&gt;&lt;/ins&gt;
&lt;script&gt;
     (adsbygoogle = window.adsbygoogle || []).push({});
&lt;/script&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1735630368086&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import Header from &quot;@/components/Header&quot;; 
import Footer from &quot;@/components/shared/Footer&quot;;&lt;/code&gt;&lt;/pre&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;b&gt;import alias&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;물론 alias를 사용할 때 문제점은 클릭해 해당 코드로 넘어가지지 않는 다는 건데요&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;alias를 세팅하고 우선 '../..' 를 사용해도 괜찮아요&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 '@/~' 하면 되니까요&lt;/p&gt;
&lt;p data-ke-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>
      <category>Alias</category>
      <category>NeXT</category>
      <category>src/</category>
      <category>프론트엔드</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/111</guid>
      <comments>https://nicksoon.tistory.com/entry/next-%ED%8F%B4%EB%8D%94-src-%EA%B7%B8%EB%A6%AC%EA%B3%A0-import-alias#entry111comment</comments>
      <pubDate>Tue, 31 Dec 2024 16:34:57 +0900</pubDate>
    </item>
    <item>
      <title>ESLint란</title>
      <link>https://nicksoon.tistory.com/entry/ESLint%EB%9E%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;next.js 를 시작하면서 이것 저것 나오는데 궁금한 것들이 있어 정리해 보았습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1735628464061&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;npx create-next-app@latest .&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 next를 설치를 하게 되면서 여러가지 물어보더라고요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 타입스크립트를 사용할 거니? yes~! 이거 써야 할 말이 있으니까요?!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 ESline을 사용할 거니? Would you like to use eslint?&amp;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;여시거 no를 사용하고 싶었지만 왜 no여야 하는지 왜 yes여야 하는지 고민을 해보고 싶었어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 ESline을 사용하면 많은 어려움이 있었기 때문에 사용을 하고 싶지 않았어요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 왜 나에게 문제가 발생을 했는지 찾는 것도 좋을 것 같아 ESline을 찾아봤어요&lt;/p&gt;
&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;ESLint&lt;/b&gt;는 &lt;b&gt;JavaScript 및 TypeScript 코드에서 오류를 찾아내고 스타일을 유지하도록 도와주는 정적 코드 분석 도구&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;다시 생각을 해보면 이전 JavaScript가 준 너프함과 안일함으로 인해 문제가 발생하지 않았나 생각해 봅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 다시 알아봐야죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;ESLint의 주요 역할&lt;/b&gt;&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;- 문법 오류, 사용하지 않는 변수, 선언되지 않은 변수 사용 등 코드 품질 문제를 찾아냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예:&lt;/p&gt;
&lt;pre id=&quot;code_1735628789759&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let unusedVariable;
console.log(a); // 'a' is not defined (에러)&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;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;예: 세미콜론 사용 여부, 들여쓰기 크기(스페이스 2개 vs 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;3. 자동 수정 지원&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 일부 문제는 eslint --fix 명령어로 자동으로 해결 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예: 잘못된 들여쓰기, 세미콜론 누락 등.&lt;/p&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;그런데 저는 엄청 고생한 기억이 있어서 더 찾아보았습니다.&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;ESLint의 구성 요소&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 규칙(Rules)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- ESLint는 다양한 규칙을 제공하며, 필요에 따라 활성화하거나 비활성화할 수 있습니다.&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;no-unused-vars&lt;/b&gt;: 사용하지 않는 변수를 경고.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;eqeqeq&lt;/b&gt;: == 대신 === 사용을 강제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커스터마이징 가능한 규칙 설정 예:&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1735629006734&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{ &quot;rules&quot;: 
	{ 
        &quot;semi&quot;: [&quot;error&quot;, &quot;always&quot;], // 세미콜론을 항상 사용 
        &quot;quotes&quot;: [&quot;error&quot;, &quot;single&quot;], // 문자열은 항상 작은 따옴표 사용 
        &quot;eqeqeq&quot;: &quot;error&quot; // '==' 대신 '===' 강제 
    } 
}&lt;/code&gt;&lt;/pre&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;&lt;b&gt;2. 플러그인(Plugins)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- React, TypeScript 등 특정 라이브러리나 프레임워크에 맞는 규칙을 추가로 지원.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예: eslint-plugin-react, eslint-plugin-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;b&gt;3. 환경(Environment)&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;예: 브라우저, Node.js, ES6 등.&lt;/p&gt;
&lt;pre id=&quot;code_1735629051730&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;{ &quot;env&quot;: 
	{ 
    	&quot;browser&quot;: true, 
        &quot;node&quot;: true, 
        &quot;es6&quot;: true 
    } 
}&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;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;ESLint의 주요 장점&lt;/b&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;
&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;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;/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;Prettier와 결합하거나 Git 훅에 추가하여 코드 스타일을 자동으로 검사 및 수정.&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;p data-ke-size=&quot;size16&quot;&gt;이런 이유로 사용해 보기 했어요&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>exline</category>
      <category>Javascript</category>
      <category>NeXT</category>
      <category>프론트엔드</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/110</guid>
      <comments>https://nicksoon.tistory.com/entry/ESLint%EB%9E%80#entry110comment</comments>
      <pubDate>Tue, 31 Dec 2024 16:22:31 +0900</pubDate>
    </item>
    <item>
      <title>JavaScript Number Format 숫자 단위 변환</title>
      <link>https://nicksoon.tistory.com/entry/%EA%B8%88%EC%95%A1%EC%9D%B4-%EB%84%88%EB%AC%B4-%EB%A7%8E%EC%95%84-%EC%9A%94%EC%95%BD%EC%9D%84-%ED%95%B4%EC%95%BC-%ED%95%A0-%EB%95%8C%EC%88%AB%EC%9E%90%EA%B0%80-%ED%81%B4-%EB%95%8C</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;긴 숫자를 읽기 쉽게 변환하는 방법은 많은 곳에서 유용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히, 큰 금액이나 데이터 크기를 간결하게 표시할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문제: 긴 숫자를 읽기 쉽게 변환하기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, 24,343,800이라는 숫자를 그대로 표시하면 가독성이 떨어지고 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;이를 단위를 사용해 &quot;&lt;b&gt;2억+&lt;/b&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;아래와 같은 코드로 작성을 하면 좋을 것 같아요&lt;/p&gt;
&lt;pre id=&quot;code_1735287948325&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function formatLargeNumber(number) {
    if (typeof number !== &quot;number&quot; || isNaN(number)) {
        throw new Error(&quot;입력 값은 숫자여야 합니다.&quot;);
    }

    const units = [&quot;&quot;, &quot;만&quot;, &quot;십만+&quot;, &quot;백만+&quot;, &quot;천만+&quot;, &quot;억+&quot;, &quot;십억+&quot;];
    let unitIndex = 0;

    // 10,000 단위로 나누기 시작
    do {
        if (unitIndex === 0) {
            number = Math.floor(number / 10000); // 첫 번째는 10,000으로 나눔
        } else {
            number = Math.floor(number / 10); // 이후부터는 10씩 나눔
        }
        unitIndex++;
    } while (number &amp;gt;= 10 &amp;amp;&amp;amp; unitIndex &amp;lt; units.length - 1);

    return `${Math.floor(number)}${units[unitIndex]}`;
}

// 예제 사용
console.log(formatLargeNumber(24343800)); // 결과: &quot;2억+&quot;
console.log(formatLargeNumber(123456));   // 결과: &quot;1십만+&quot;
console.log(formatLargeNumber(9876543210)); // 결과: &quot;9십억+&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;코드 작동 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;입력 검증&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입력 값이 숫자인지 확인합니다. 숫자가 아니면 오류를 발생시킵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt; 단위 배열 정의 &lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1735288032219&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const units = [&quot;&quot;, &quot;만&quot;, &quot;십만+&quot;, &quot;백만+&quot;, &quot;천만+&quot;, &quot;억+&quot;, &quot;십억+&quot;];&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;units 배열은 단위(만, 십만+, 백만+ 등)를 나타냅니다.&lt;/p&gt;
&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;첫 번째 반복:&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;10000으로 나눠 만 단위로 줄입니다.&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;10씩 나눠 단위를 점점 올립니다.&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;/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;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;633&quot; data-origin-height=&quot;846&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBs9Zg/btsLyUN48mu/XAskn688S2Ou0tReK0Akt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBs9Zg/btsLyUN48mu/XAskn688S2Ou0tReK0Akt0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBs9Zg/btsLyUN48mu/XAskn688S2Ou0tReK0Akt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBs9Zg%2FbtsLyUN48mu%2FXAskn688S2Ou0tReK0Akt0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;633&quot; height=&quot;846&quot; data-origin-width=&quot;633&quot; data-origin-height=&quot;846&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;</description>
      <category>개발/개발 필기</category>
      <category>Javascript</category>
      <category>javascript 함수</category>
      <category>숫자 단위 변환</category>
      <category>숫자 변환</category>
      <category>숫자 처리</category>
      <category>한국어 단위</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/109</guid>
      <comments>https://nicksoon.tistory.com/entry/%EA%B8%88%EC%95%A1%EC%9D%B4-%EB%84%88%EB%AC%B4-%EB%A7%8E%EC%95%84-%EC%9A%94%EC%95%BD%EC%9D%84-%ED%95%B4%EC%95%BC-%ED%95%A0-%EB%95%8C%EC%88%AB%EC%9E%90%EA%B0%80-%ED%81%B4-%EB%95%8C#entry109comment</comments>
      <pubDate>Fri, 27 Dec 2024 17:40:29 +0900</pubDate>
    </item>
    <item>
      <title>JavaScript 연산자 정리</title>
      <link>https://nicksoon.tistory.com/entry/JavaScript-%EC%97%B0%EC%82%B0%EC%9E%90-%EC%A0%95%EB%A6%AC</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript의 &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-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 연산자의 개념&lt;/b&gt;&lt;/h2&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;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고 문서: MDN 자바스크립트 연산자&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 값과 표현식&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;리터럴 (Literal)&lt;/b&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;: 1, 123&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문자열 리터럴&lt;/b&gt;: 'hello', &quot;world&quot;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;템플릿 리터럴&lt;/b&gt;: 안녕, ${name}&lt;/li&gt;
&lt;li&gt;&lt;b&gt;함수 리터럴&lt;/b&gt;: function() {}&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;표현식 (Expression)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;값으로 평가될 수 있는 코드&lt;/b&gt;를 의미합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;let b;       // 선언문
b = 2;       // 표현식, 할당문

let a = b = 2; // 표현식
console.log(a); // 2 출력
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 산술 연산자 (Arithmetic Operators)&lt;/b&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;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;+&lt;/td&gt;
&lt;td&gt;더하기&lt;/td&gt;
&lt;td&gt;5 + 2 &amp;rarr; 7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;빼기&lt;/td&gt;
&lt;td&gt;5 - 2 &amp;rarr; 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;곱하기&lt;/td&gt;
&lt;td&gt;5 * 2 &amp;rarr; 10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/&lt;/td&gt;
&lt;td&gt;나누기&lt;/td&gt;
&lt;td&gt;5 / 2 &amp;rarr; 2.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;%&lt;/td&gt;
&lt;td&gt;나머지&lt;/td&gt;
&lt;td&gt;5 % 2 &amp;rarr; 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;**&lt;/td&gt;
&lt;td&gt;거듭제곱&lt;/td&gt;
&lt;td&gt;5 ** 2 &amp;rarr; 25&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;console.log(5 + 2); // 7
console.log(5 % 2); // 1
console.log(5 ** 2); // 25 (ES7+)
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주의: 문자열과 숫자를 함께 사용할 경우 문자열 연결이 됩니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;let text = '1' + 1; // 문자열 '11'
console.log(text);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 단항 연산자 (Unary Operators)&lt;/b&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;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;+&lt;/td&gt;
&lt;td&gt;양수 변환&lt;/td&gt;
&lt;td&gt;+5 &amp;rarr; 5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;음수 변환&lt;/td&gt;
&lt;td&gt;-5 &amp;rarr; -5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;!&lt;/td&gt;
&lt;td&gt;논리 부정&lt;/td&gt;
&lt;td&gt;!true &amp;rarr; false&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;let unaryA = 5;
unaryA = -unaryA; // -5
console.log(unaryA);

let unaryBoolean = true;
console.log(!unaryBoolean); // false
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;숫자로 변환&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;console.log(+false);       // 0
console.log(+null);        // 0
console.log(+undefined);   // NaN
console.log(!!1);          // true
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 할당 연산자 (Assignment Operators)&lt;/b&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;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;=&lt;/td&gt;
&lt;td&gt;할당&lt;/td&gt;
&lt;td&gt;a = 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;+=&lt;/td&gt;
&lt;td&gt;더한 후 할당&lt;/td&gt;
&lt;td&gt;a += 2 &amp;rarr; a = a + 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;-=&lt;/td&gt;
&lt;td&gt;뺀 후 할당&lt;/td&gt;
&lt;td&gt;a -= 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;*=&lt;/td&gt;
&lt;td&gt;곱한 후 할당&lt;/td&gt;
&lt;td&gt;a *= 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;/=&lt;/td&gt;
&lt;td&gt;나눈 후 할당&lt;/td&gt;
&lt;td&gt;a /= 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;%=&lt;/td&gt;
&lt;td&gt;나머지를 구한 후 할당&lt;/td&gt;
&lt;td&gt;a %= 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;**=&lt;/td&gt;
&lt;td&gt;거듭제곱 후 할당&lt;/td&gt;
&lt;td&gt;a **= 2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;let a = 1;
a += 2; // a = a + 2 &amp;rarr; 3
console.log(a);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. 증감 연산자 (Increment &amp;amp; Decrement Operators)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연산자 설명 예시&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;++&lt;/td&gt;
&lt;td&gt;1 증가&lt;/td&gt;
&lt;td&gt;a++, ++a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;--&lt;/td&gt;
&lt;td&gt;1 감소&lt;/td&gt;
&lt;td&gt;a--, --a&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;let a = 0;
console.log(a++); // 0 &amp;rarr; 출력 후 증가
console.log(++a); // 2 &amp;rarr; 먼저 증가 후 출력
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;7. 비교 연산자 (Equality Operators)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연산자 설명 예시&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;==&lt;/td&gt;
&lt;td&gt;값이 같으면 true&lt;/td&gt;
&lt;td&gt;2 == '2' &amp;rarr; true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;===&lt;/td&gt;
&lt;td&gt;값과 타입이 같으면 true&lt;/td&gt;
&lt;td&gt;2 === '2' &amp;rarr; false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;!=&lt;/td&gt;
&lt;td&gt;값이 다르면 true&lt;/td&gt;
&lt;td&gt;2 != 3 &amp;rarr; true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;!==&lt;/td&gt;
&lt;td&gt;값 또는 타입이 다르면 true&lt;/td&gt;
&lt;td&gt;2 !== '2' &amp;rarr; true&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;console.log(2 == '2');  // true (타입 무시)
console.log(2 === '2'); // false (타입까지 비교)

const obj1 = { name: 'js' };
const obj2 = { name: 'js' };
console.log(obj1 == obj2);  // false &amp;rarr; 메모리 주소가 다름
console.log(obj1.name == obj2.name); // true &amp;rarr; 값이 같음
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;8. 연산자 우선순위&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연산자에는 우선순위가 있습니다. 곱셈, 나눗셈이 덧셈, 뺄셈보다 먼저 실행됩니다.&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;let a = 2, b = 3;
let result = a + b * 4;
console.log(result); // 14 &amp;rarr; b * 4 먼저 계산

result = (a + b) * 4;
console.log(result); // 20 &amp;rarr; 괄호가 우선순위
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우선순위 참고: MDN 연산자 우선순위&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마무리하며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연산자는 JavaScript의 기본이자 핵심 개념입니다. 각 연산자의 동작을 이해하고 잘 활용하면 더욱 효율적이고 깔끔한 코드를 작성할 수 있습니다.&lt;/p&gt;</description>
      <category>개발/JavaScript</category>
      <category>Javascript</category>
      <category>연산자 정리</category>
      <category>프로그래밍 기초</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/108</guid>
      <comments>https://nicksoon.tistory.com/entry/JavaScript-%EC%97%B0%EC%82%B0%EC%9E%90-%EC%A0%95%EB%A6%AC#entry108comment</comments>
      <pubDate>Mon, 16 Dec 2024 23:06:46 +0900</pubDate>
    </item>
    <item>
      <title>JavaScript 기본 타입과 메모리 이해하기</title>
      <link>https://nicksoon.tistory.com/entry/JavaScript-%EA%B8%B0%EB%B3%B8-%ED%83%80%EC%9E%85%EA%B3%BC-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;JavaScript의 기본 데이터 타입&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 숫자 타입 (Number)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;숫자 타입은 정수, 음수, 실수를 포함합니다.&lt;/p&gt;
&lt;pre class=&quot;lasso&quot;&gt;&lt;code&gt;let integer = 123; // 정수
let negative = -123; // 음수
let double = 1.23; // 실수

console.log(integer); // 123
console.log(negative); // -123
console.log(double); // 1.23

// 다양한 진법
let binary = 0b1111011; // 2진수
let octal = 0o173; // 8진수
let hex = 0x7b; // 16진수

console.log(binary); // 123
console.log(octal);  // 123
console.log(hex);    // 123
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;NaN과 Infinity&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;console.log(0 / 123); // 0
console.log(123 / 0); // Infinity
console.log(123 / -0); // -Infinity
console.log(123 / 'text'); // NaN (Not a Number)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;BigInt&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BigInt는 매우 큰 정수를 표현할 때 사용합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;let bigInt = 12345678910111213141516171819202122232425262728293031323334353637n;
console.log(bigInt); // 123456789...
console.log(typeof bigInt); // bigint
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 문자열 타입 (String)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열은 텍스트 데이터를 표현하는 타입입니다. 작은 따옴표(')나 큰 따옴표(&quot;), 백틱(```)을 사용합니다.&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;let string = '안녕하세요';
string = `안녕!`;
console.log(string); // 안녕!

// 특수 문자 사용 예시
string = '안녕\\n nicksoon!\\t\\t 내 이름은\\\\';
console.log(string); // 줄바꿈, 탭, 백슬래시 포함&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;템플릿 리터럴&lt;/b&gt;:&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;let id = 'nicksoon';
let greeting = `안녕, ${id}  \\n즐거운 하루 보내요!`;
console.log(greeting);&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 불리언 타입 (Boolean)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참(true)과 거짓(false)만을 표현합니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;let isFree = true;
let isActivated = false;
console.log(isFree); // true
console.log(isActivated); // false

// Truthy와 Falsy 값
console.log(!!0); // false
console.log(!!1); // true
console.log(!!''); // false
console.log(!!' '); // true
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4. Null과 Undefined&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;null은 비어있는 값, undefined는 값이 할당되지 않은 상태를 나타냅니다.&lt;/p&gt;
&lt;pre class=&quot;gams&quot;&gt;&lt;code&gt;let variable;
console.log(variable); // undefined

variable = null;
console.log(variable); // null
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;객체 타입 (Object)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체는 여러 데이터를 묶어서 저장할 수 있는 복합 데이터 타입입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;객체 생성과 사용&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;xl&quot;&gt;&lt;code&gt;let apple = {
    name: 'apple',
    color: 'red',
    display: ' '
};
let orange = {
    name: 'orange',
    color: 'orange',
    display: ' '
};

console.log(apple);
console.log(orange);
&lt;/code&gt;&lt;/pre&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;*원시 타입(Primitive Type)**은 값 자체를 복사하지만, **객체(Object)**는 참조값(메모리 주소)을 복사합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;let a = 1;
let b = a; // 값 복사
console.log(a, b); // 1, 1

let appleObject = { name: 'apple' };
let orangeObject = appleObject; // 참조 복사

appleObject.name = 'orange';
console.log(appleObject); // { name: 'orange' }
console.log(orangeObject); // { name: 'orange' }
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체를 복사하려면 다음과 같이 **얕은 복사(Shallow Copy)**를 사용합니다:&lt;/p&gt;
&lt;pre class=&quot;xquery&quot;&gt;&lt;code&gt;let finappleObject = Object.assign({}, appleObject);
let mango = { ...appleObject };

finappleObject.name = '파인애플';
mango.name = 'mango';

console.log(finappleObject); // { name: '파인애플' }
console.log(mango); // { name: 'mango' }
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;const와 let&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수를 선언할 때 const와 let의 차이를 알아봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재할당 가능 여부 변경 가능 여부&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 26.0465%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 37.5582%;&quot;&gt;재할당 reassignable&lt;/td&gt;
&lt;td style=&quot;width: 36.279%;&quot;&gt;변경 Mutable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 26.0465%;&quot;&gt;let&lt;/td&gt;
&lt;td style=&quot;width: 37.5582%;&quot;&gt;Yes&lt;/td&gt;
&lt;td style=&quot;width: 36.279%;&quot;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 26.0465%;&quot;&gt;const&lt;/td&gt;
&lt;td style=&quot;width: 37.5582%;&quot;&gt;No&lt;/td&gt;
&lt;td style=&quot;width: 36.279%;&quot;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre class=&quot;processing&quot;&gt;&lt;code&gt;let exA = 1;
exA = 2; // 가능

const exText = 'hello';
// exText = 'hi'; // 불가능

const exConstApple = {
    name: 'apple',
    color: 'red'
};
exConstApple.color = 'green'; // 객체의 속성 변경은 가능
console.log(exConstApple);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;typeof를 통한 타입 확인&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript는 &lt;b&gt;동적 타입 언어&lt;/b&gt;이므로 변수의 타입이 실행 중에 변경될 수 있습니다.&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;let typeofVariable;
console.log(typeof typeofVariable); // undefined

typeofVariable = 'Hello';
console.log(typeof typeofVariable); // string

typeofVariable = 123;
console.log(typeof typeofVariable); // number

typeofVariable = function () {};
console.log(typeof typeofVariable); // function

typeofVariable = {};
console.log(typeof typeofVariable); // object
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마무리하며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글에서는 JavaScript의 &lt;b&gt;기본 데이터 타입&lt;/b&gt;과 &lt;b&gt;객체 타입&lt;/b&gt;, 그리고 변수의 활용법에 대해 다루었습니다.&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/JavaScript</category>
      <category>Javascript</category>
      <category>javascript 변수</category>
      <category>javascript 학습</category>
      <category>객체와 원시 타입</category>
      <category>프론트엔드 개발</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/107</guid>
      <comments>https://nicksoon.tistory.com/entry/JavaScript-%EA%B8%B0%EB%B3%B8-%ED%83%80%EC%9E%85%EA%B3%BC-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0#entry107comment</comments>
      <pubDate>Mon, 16 Dec 2024 22:05:47 +0900</pubDate>
    </item>
    <item>
      <title>억까 문제(문제 해결방안, 사고력 키우기)</title>
      <link>https://nicksoon.tistory.com/entry/%EC%96%B5%EA%B9%8C-%EB%AC%B8%EC%A0%9C%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EC%95%88-%EC%82%AC%EA%B3%A0%EB%A0%A5-%ED%82%A4%EC%9A%B0%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번에 어느 분께 문제 해결방안에 대해서 이야기를 한 적이 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[문제]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 기업은 고객에게 상품을 배송하기 위해 여러 단계를 거치는 물류 시스템을 운영하고 있다. 상품은 1차 창고에서 출발하여 2차 창고, 3차 창고를 거쳐 고객에게 도착한다. 각 구간의 운송 시간은 1차 창고에서 2차 창고까지 1시간, 2차 창고에서 3차 창고까지 2시간 30분, 3차 창고에서 고객까지 2시간이 소요된다. 또한 각 단계에서 상하차 시간이 추가로 소요되며, 1차 창고에서 상하차 시간은 30분, 2차 창고에서 상하차 시간은 1시간, 3차 창고에서 상하차 시간은 1시간이다. 운송 과정에서 각 구간별로 비용이 발생하며 1차 창고에서 2차 창고까지의 운송 비용은 100만 원, 2차 창고에서 3차 창고까지의 운송 비용은 50만 원, 3차 창고에서 고객까지의 운송 비용은 10만 원이다. 이 시스템에는 몇 가지 제약 조건이 있는데, 상품은 반드시 오전 7시까지 고객에게 도착해야 하며 배송은 매일 00시에 시작한다. 운송 시간과 상하차 시간을 모두 고려해야 한다. 이 기업의 물류 규모는 1차 창고가 1개, 2차 창고가 도시별로 20개, 3차 창고가 마을별로 50 곱하기 20개로 총 1000개이며 고객은 100 곱하기 50 곱하기 20명으로 총 10만 명이다.&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;&lt;b&gt;억지 스러운 문제입니다. 정답이 없어요&amp;nbsp;&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;문제 분석&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주어진 조건&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;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;1차 -&amp;gt; 2차:&lt;/b&gt; 1시간&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2차 -&amp;gt; 3차:&lt;/b&gt; 2시간 30분&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3차 -&amp;gt; 고객:&lt;/b&gt; 2시간&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;1차 상하차:&lt;/b&gt; 30분&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2차 상하차:&lt;/b&gt; 1시간&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3차 상하차:&lt;/b&gt; 1시간&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;1차 -&amp;gt; 2차:&lt;/b&gt; 100만 원&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2차 -&amp;gt; 3차:&lt;/b&gt; 50만 원&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3차 -&amp;gt; 고객:&lt;/b&gt; 10만 원&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;고객에게 오전 7시까지 도착&lt;/b&gt;해야 함.&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;1차 창고:&lt;/b&gt; 1개&lt;/li&gt;
&lt;li&gt;&lt;b&gt;2차 창고:&lt;/b&gt; 도시별 20개&lt;/li&gt;
&lt;li&gt;&lt;b&gt;3차 창고:&lt;/b&gt; 마을별 50 * 20개&lt;/li&gt;
&lt;li&gt;&lt;b&gt;고객:&lt;/b&gt; 100 * 50 * 20명&lt;/li&gt;
&lt;/ul&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;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;고객까지 도착하는 총 소요 시간:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;운송 시간:&lt;/b&gt; &lt;span&gt;&lt;span&gt;1+2.5+2=5.5시간1 + 2.5 + 2 = 5.5&lt;/span&gt;&lt;span aria-hidden=&quot;true&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;/li&gt;
&lt;li&gt;&lt;b&gt;상하차 시간:&lt;/b&gt; &lt;span&gt;&lt;span&gt;0.5+1+1=2.5시간0.5 + 1 + 1 = 2.5시간&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;총:&lt;/b&gt; &lt;span&gt;&lt;span&gt;5.5+2.5=8시간5.5 + 2.5 = 8시간&lt;/span&gt;&lt;/span&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;&lt;span&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;1. 무조건 00시에 출발해야 한다&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;분명 기업에서는 다른 투자나 시간대를 변경하거나 다른 상황을 만들어 내겠지만&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 1:1로 대화하면서 해결?을 그것도 개발자에게? 개발적으로 동선을 생각하라는 건가?&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알고리즘 문제인가? 한참을 고민하다가&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상하차 시간을 줄이는 것 뿐이라고 이야기를 했어요&amp;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;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;friends2&quot; data-emoticon-name=&quot;006&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends2/large/006.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends2/large/006.png&quot; width=&quot;150&quot; /&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;&amp;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;ol style=&quot;list-style-type: decimal;&quot; data-pm-slice=&quot;3 3 []&quot; data-spread=&quot;false&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;span&gt; 문제의 비현실적인 측면을 인지하고, 이를 논리적으로 설명하는 능력.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;현실적인 한계의 인지:&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 자원이 부족하고 제약 조건이 많은 상황에서 가능한 대안을 제시하는 능력.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;압박 테스트:&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;다시 문제를 바꿔서 개발자 적으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- End day는 짧다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 인원은 한정적이다&lt;/p&gt;
&lt;p data-ke-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;u&gt;&lt;b&gt;&quot;그럼 면접을 볼때라면 이렇겠죠 야근을 해서라도 하겠습니다!&quot;&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 위 시간이 야근을 포함해서 준 시간이다 라고 하면요?&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;friends2&quot; data-emoticon-name=&quot;015&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends2/large/015.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends2/large/015.png&quot; width=&quot;150&quot; /&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 이일을 이렇게 생각하고 정리해 봅니다.&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 3 []&quot; 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;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;End day는 짧다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;인원은 한정적이다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;시작은 이미 지났다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;야근을 포함해서도 시간이 부족하다면 어떻게 해야 할까요? &lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;저는 다음과 같은 과정을 통해 해결책을 제시할 수 있다고 생각합니다:&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;1. 비현실적인 조건을 인지시키기&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&quot;이 문제는 주어진 시간 내에 모든 요구 사항을 만족시키는 것이 현실적으로 어렵습니다.&quot; 문제를 요청한 대상에게 비현실적인 조건임을 논리적으로 전달해야 합니다. 이를 통해 문제의 범위를 재조정하거나, 최소한의 목표를 명확히 할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;2. 우선순위 설정&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&quot;모든 작업이 중요하다고 하지만, 반드시 처리해야 하는 핵심 작업부터 진행해야 합니다.&quot;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;우선순위를 명확히 하고, 뒤로 미룰 수 있는 작업은 과감히 제외하거나 축소합니다. 예를 들어, 고객에게 상품이 도착하기 위해 반드시 필요한 단계(MVP)를 정의하고, 부수적인 작업은 후순위로 둡니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;3. 팀 내 효율적인 분배&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&quot;남은 시간 동안 팀원들과 역할을 명확히 나누고, 각자가 맡은 부분을 빠르게 처리할 수 있도록 합니다.&quot;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;회의는 간결하게 진행하며, 작업을 최대한 분산시켜 병렬적으로 처리합니다. 효율성을 높이기 위해 중복 작업이나 불필요한 과정을 제거합니다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;4. 생산성을 극대화&lt;/span&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&quot;코드 리뷰나 반복 작업은 생략하거나 간소화하고, 가능한 빠르게 배포 가능한 상태로 만듭니다.&quot;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;기술적 부채를 감수하더라도, 지금 당장 필요한 작업에 집중합니다. 배포 후에 보완할 수 있는 부분은 다음 단계로 미룹니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;면접관이 일부러 말이 안 되는 상황을 제시했을 경우,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현실적 한계와 대안을 논리적으로 설명하면서도 협조적인 태도를 보여주는 것이 중요하다고 생각이 듭니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;friends2&quot; data-emoticon-name=&quot;014&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends2/large/014.png&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends2/large/014.png&quot; width=&quot;150&quot; /&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;h3 data-pm-slice=&quot;1 1 []&quot; 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;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;제한된 조건 내에서 최선의 결과를 도출하려는 태도입니다.&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;</description>
      <category>개발/개발 필기</category>
      <category>개발자 사고방식</category>
      <category>면접 질문</category>
      <category>문제 해결</category>
      <category>비현실적인 요구</category>
      <category>생산성 향상</category>
      <category>압박 테스트</category>
      <category>우선순위 설정</category>
      <category>팀워크</category>
      <category>프로젝트 관리</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/106</guid>
      <comments>https://nicksoon.tistory.com/entry/%EC%96%B5%EA%B9%8C-%EB%AC%B8%EC%A0%9C%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%EB%B0%A9%EC%95%88-%EC%82%AC%EA%B3%A0%EB%A0%A5-%ED%82%A4%EC%9A%B0%EA%B8%B0#entry106comment</comments>
      <pubDate>Mon, 16 Dec 2024 12:04:37 +0900</pubDate>
    </item>
    <item>
      <title>JavaScript 기초: 변수(Variable)와 메모리 이해하기</title>
      <link>https://nicksoon.tistory.com/entry/JavaScript-%EA%B8%B0%EC%B4%88-%EB%B3%80%EC%88%98Variable%EC%99%80-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%9D%B4%ED%95%B4%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;b&gt;컴퓨터의 메모리와 JavaScript 변수&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 data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;컴퓨터의 구성 요소와 메모리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터는 크게 &lt;b&gt;하드디스크, 연산(CPU), 메모리&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;CPU&lt;/b&gt;: 데이터를 처리합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;메모리&lt;/b&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;p data-ke-size=&quot;size16&quot;&gt;메모리는 여러 칸으로 나누어져 있으며, 각 칸은 &lt;b&gt;1바이트(byte)&lt;/b&gt; 단위로 구성됩니다. 예시:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;1byte | 1byte | 1byte | 1byte | ...
&lt;/code&gt;&lt;/pre&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;Code 영역&lt;/b&gt;: 실행할 코드가 저장됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Data 영역&lt;/b&gt;: 전역 변수 및 상수가 저장됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Stack 영역&lt;/b&gt;: 함수 호출과 지역 변수가 저장됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Heap 영역&lt;/b&gt;: 동적으로 생성되는 데이터가 저장됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;JavaScript의 변수(Variable)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수는 데이터를 저장하는 &lt;b&gt;이름이 주어진 메모리 공간&lt;/b&gt;입니다. 변수를 사용하면 메모리 주소를 몰라도 이름만으로 값을 저장하고 불러올 수 있습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;변수의 기본 개념&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수를 선언하고 값을 할당하는 기본 구조는 다음과 같습니다:&lt;/p&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt;let a = 0; // let(키워드) a(변수 이름) = (할당 연산자) 0(값);
console.log(a); // 0 출력

a = 1;
console.log(a); // 1 출력

let b; // 값 할당 없이 변수 선언만 함
console.log(b); // undefined 출력

b = 2;
console.log(b); // 2 출력
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;변수 이름 짓기 (Naming Variables)&lt;/b&gt;&lt;/h3&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;추천 문서: MDN - 변수 이해하기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;변수 이름 규칙&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수 이름을 지을 때 지켜야 할 규칙이 있습니다:&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;사용 가능한 문자&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;라틴 문자: a-z, A-Z, 0-9, _, $&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대소문자 구분&lt;/b&gt;: apple과 Apple은 서로 다른 변수입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Camel Case 추천&lt;/b&gt;: 단어를 이어 쓸 때 camelCase 방식 사용 (likeThis).&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;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;: let 1apple; (X)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;특수문자 사용 불가&lt;/b&gt;: _와 $만 예외적으로 허용됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;한국어 및 이모지 사용 금지&lt;/b&gt;: let 사과;, let  ; (X)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;예약어 사용 금지&lt;/b&gt;: 예약어는 변수명으로 사용할 수 없습니다. (&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#keywords&quot;&gt;예약어 목록&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;좋은 변수 이름 예시&lt;/b&gt;&lt;/h3&gt;
&lt;pre class=&quot;typescript&quot;&gt;&lt;code&gt;// 나쁜 예제
let number = 20;

// 좋은 예제
let myAge = 20; // 나이를 표현하는 의미 있는 이름

// 나쁜 예제
let audio1;
let audio2;

// 좋은 예제
let backgroundAudio;
let windAudio;

// 꿀팁: 찾기 쉬운 변수명 사용
let audioBackground;
let audioWind;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;변수 이름이 중요한 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수 이름을 잘 지으면 &lt;b&gt;코드의 가독성&lt;/b&gt;이 좋아지고, 팀 프로젝트에서도 더 원활한 협업이 가능합니다. 단순히 a, b처럼 아무 의미 없는 이름 대신, &lt;b&gt;저장된 값이 무엇을 나타내는지 바로 이해할 수 있는 이름&lt;/b&gt;을 사용해 보세요!&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마무리하며&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;변수는 프로그래밍에서 가장 기본적이면서 중요한 개념입니다. 메모리의 구조를 이해하고, 올바르게 변수를 선언하고 사용하면 더욱 &lt;b&gt;깔끔하고 유지보수하기 쉬운 코드&lt;/b&gt;를 작성할 수 있습니다.&lt;/p&gt;</description>
      <category>개발/JavaScript</category>
      <category>Javascript</category>
      <category>js</category>
      <category>naming</category>
      <category>valable</category>
      <category>메모리</category>
      <category>변수</category>
      <category>변수이름</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/105</guid>
      <comments>https://nicksoon.tistory.com/entry/JavaScript-%EA%B8%B0%EC%B4%88-%EB%B3%80%EC%88%98Variable%EC%99%80-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0#entry105comment</comments>
      <pubDate>Mon, 16 Dec 2024 00:21:38 +0900</pubDate>
    </item>
    <item>
      <title>JavaScript를 실행하는 방법: 브라우저와 Node.js 활용하기</title>
      <link>https://nicksoon.tistory.com/entry/JavaScript%EB%A5%BC-%EC%8B%A4%ED%96%89%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%99%80-Nodejs-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0</link>
      <description>&lt;p style=&quot;color: #333333; 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;JavaScript를 실행하는 데에는 두 가지 주요 방법이 있습니다. 바로 &lt;b&gt;브라우저&lt;/b&gt;와 &lt;b&gt;Node.js&lt;/b&gt;를 사용하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래에서 각각의 방법과 실행 방법을 단계별로 알아보겠습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. &lt;b&gt;브라우저에서 JavaScript 실행하기&lt;/b&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;준비 단계: Chrome 다운로드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 브라우저에서 JavaScript를 실행하려면 Chrome 같은 브라우저가 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Chrome은 다음 링크에서 다운로드할 수 있습니다:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;a href=&quot;https://www.google.com/chrome/&quot;&gt;Chrome 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실행 방법: Hello World 출력하기&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;Chrome 브라우저를 열기&lt;/b&gt;Chrome을 실행한 후, 개발자 도구를 열어야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;개발자 도구 실행&lt;/b&gt;Windows: Ctrl + Shift + JMac: Cmd + Option + J&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JavaScript 코드 입력&lt;/b&gt;개발자 도구의 &lt;b&gt;Console 탭&lt;/b&gt;에서 아래 코드를 입력하고 실행해 보세요:&lt;/li&gt;
&lt;li&gt;console.log(&quot;Hello World!&quot;);&lt;/li&gt;
&lt;li&gt;&lt;b&gt;출력 확인&lt;/b&gt;Console 창에 Hello World!라는 메시지가 출력됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. &lt;b&gt;VS Code를 사용해 JavaScript 실행하기&lt;/b&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;준비 단계: VS Code 다운로드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 작성하고 실행할 수 있는 편리한 에디터인 VS Code를 다운로드하세요:&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;  &lt;a href=&quot;https://code.visualstudio.com/download&quot;&gt;VS Code 다운로드&lt;/a&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;VS Code로 JavaScript 실행하기&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;VS Code 설치 및 실행&lt;/b&gt;다운로드한 VS Code를 설치하고 실행합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JavaScript 파일 생성&lt;/b&gt;index.js라는 새 파일을 만듭니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;코드 작성&lt;/b&gt;아래와 같은 JavaScript 코드를 작성합니다:&lt;/li&gt;
&lt;li&gt;console.log(&quot;Hello World!&quot;);&lt;/li&gt;
&lt;li&gt;&lt;b&gt;터미널에서 실행&lt;/b&gt;VS Code 하단의 터미널을 열고 다음 명령어를 실행합니다:터미널에 Hello World!가 출력됩니다.&lt;/li&gt;
&lt;li&gt;node index.js&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. &lt;b&gt;HTML 파일에서 JavaScript 실행하기&lt;/b&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실행 준비: HTML 파일 생성&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;index.html 파일 생성&lt;/b&gt;아래와 같이 HTML 파일을 작성합니다:&lt;/li&gt;
&lt;li&gt;html 코드 복사 &amp;lt;!DOCTYPE html&amp;gt; &amp;lt;html lang=&quot;en&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;Hello World&amp;lt;/title&amp;gt; &amp;lt;/head&amp;gt; &amp;lt;body&amp;gt; &amp;lt;h1&amp;gt;Hello World!&amp;lt;/h1&amp;gt; &amp;lt;script&amp;gt; console.log(&quot;Hello World!&quot;); &amp;lt;/script&amp;gt; &amp;lt;/body&amp;gt; &amp;lt;/html&amp;gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Live Server로 실행&lt;/b&gt;VS Code에서 &lt;b&gt;Live Server&lt;/b&gt; 플러그인을 설치한 후, HTML 파일을 실행합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;결과 확인&lt;/b&gt;브라우저에서 개발자 도구(F12)를 열고 &lt;b&gt;Console&lt;/b&gt; 탭을 확인하면 Hello World!가 출력됩니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. &lt;b&gt;Node.js에서 JavaScript 실행하기&lt;/b&gt;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;준비 단계: Node.js 다운로드&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.js는 JavaScript를 브라우저 외부에서 실행할 수 있게 해줍니다. Node.js가 설치되어 있는지 확인하려면 터미널에서 다음 명령어를 입력하세요:&lt;/p&gt;
&lt;pre class=&quot;php&quot; data-ke-language=&quot;php&quot;&gt;&lt;code&gt;node -v&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.js가 설치되어 있지 않다면 &lt;a href=&quot;https://nodejs.org/&quot;&gt;Node.js 다운로드&lt;/a&gt; 페이지에서 설치하세요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Node.js로 JavaScript 실행하기&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;index.js 파일 생성&lt;/b&gt;다음 코드를 작성한 후 저장합니다:&lt;/li&gt;
&lt;li&gt;console.log(&quot;Hello World!&quot;);&lt;/li&gt;
&lt;li&gt;&lt;b&gt;터미널에서 실행&lt;/b&gt;파일이 있는 디렉터리로 이동한 후, 아래 명령어를 실행합니다:Hello World!가 출력됩니다.&lt;/li&gt;
&lt;li&gt;node index.js&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Nodemon으로 자동 실행&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Node.js 파일을 실행할 때마다 node index.js 명령어를 입력하기 번거롭다면, &lt;b&gt;Nodemon&lt;/b&gt;을 설치해 자동으로 실행되도록 설정할 수 있습니다:&lt;/p&gt;
&lt;pre class=&quot;php&quot; data-ke-language=&quot;php&quot;&gt;&lt;code&gt;npm install nodemon -g&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 아래와 같이 Nodemon으로 파일을 실행하면, 파일이 변경될 때 자동으로 실행됩니다:&lt;/p&gt;
&lt;pre class=&quot;php&quot; data-ke-language=&quot;php&quot;&gt;&lt;code&gt;nodemon index.js&lt;/code&gt;&lt;/pre&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;/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;b&gt;브라우저&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;개발자 도구에서 Console 사용&lt;/td&gt;
&lt;td&gt;브라우저에서 바로 JavaScript 실행 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;VS Code&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;Node.js와 터미널 사용&lt;/td&gt;
&lt;td&gt;다양한 JavaScript 파일 실행 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;HTML&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&amp;lt;script&amp;gt; 태그 사용&lt;/td&gt;
&lt;td&gt;웹 페이지와 함께 실행 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Node.js&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;node 명령어 사용&lt;/td&gt;
&lt;td&gt;서버 환경에서 실행 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/JavaScript</category>
      <category>javascritp</category>
      <category>node</category>
      <category>크롬확장프로그램</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/104</guid>
      <comments>https://nicksoon.tistory.com/entry/JavaScript%EB%A5%BC-%EC%8B%A4%ED%96%89%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%99%80-Nodejs-%ED%99%9C%EC%9A%A9%ED%95%98%EA%B8%B0#entry104comment</comments>
      <pubDate>Mon, 16 Dec 2024 00:14:32 +0900</pubDate>
    </item>
    <item>
      <title>JavaScript: 브라우저와 Node.js에서 동작하는 가장 많이 사용하는 언어</title>
      <link>https://nicksoon.tistory.com/entry/JavaScript-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%99%80-Nodejs%EC%97%90%EC%84%9C-%EB%8F%99%EC%9E%91%ED%95%98%EB%8A%94-%EA%B0%80%EC%9E%A5-%EB%A7%8E%EC%9D%B4-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%96%B8%EC%96%B4</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;많은 개발자들이 사용하는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;JavaScript&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에 대해 이야기해보려고 합니다. JavaScript는 프론트엔드, 백엔드 어디서든 활약하는 다재다능한 언어입니다. 이번 글에서는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;JavaScript의 동작 원리&lt;/b&gt;&lt;/span&gt;&lt;span&gt;와 공부 방법에 대해 정리해보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;JavaScript란 무엇인가?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;JavaScript는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;가볍고, 인터프리터 방식이자 Just-In-Time (JIT) 컴파일이 가능한 프로그래밍 언어&lt;/b&gt;&lt;/span&gt;&lt;span&gt;입니다. 또한 **일급 함수(First-class functions)**를 지원하며, 객체 지향, 함수형 프로그래밍 등 다양한 스타일을 지원합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;사용되는 환경&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/p&gt;
&lt;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;브라우저&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 웹 페이지의 동적 기능을 담당합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Node.js&lt;/b&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;&lt;span&gt;JavaScript는 프로토타입 기반의 &lt;/span&gt;&lt;span&gt;&lt;b&gt;단일 스레드&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 언어이며, 동적 언어 특성을 갖고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;JavaScript 정의&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: JavaScript is a lightweight, interpreted, or just-in-time compiled programming language with first-class functions. It is prototype-based, multi-paradigm, single-threaded, and dynamic, supporting object-oriented, imperative, and declarative styles (e.g., functional programming).&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;JavaScript 엔진과 동작 원리&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;JavaScript는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;런타임 시 코드&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 한 줄씩 번역해서 실행하는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;인터프리터 언어&lt;/b&gt;&lt;/span&gt;&lt;span&gt;입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이는 Java와 같은 컴파일 언어와는 다릅니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;인터프리터 방식&lt;/b&gt;&lt;/span&gt;&lt;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;JavaScript&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 코드가 실행될 때 런타임 시 한 줄씩 번역해서 실행합니다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 유연하고 실시간으로 코드 실행.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;단점&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 컴파일 언어보다 성능이 떨어질 수 있음.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;컴파일러 방식 (예: Java)&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 코드를 &lt;/span&gt;&lt;span&gt;&lt;b&gt;컴파일러&lt;/b&gt;&lt;/span&gt;&lt;span&gt;가 번역해서 실행 파일을 생성한 뒤 실행합니다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;장점&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 미리 번역되기 때문에 실행 속도가 빠름.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;b&gt;JavaScript 엔진의 발전&lt;/b&gt;&lt;/span&gt;&lt;span&gt;으로 성능이 크게 개선되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;브라우저별 JavaScript 엔진&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;브라우저마다 &lt;/span&gt;&lt;span&gt;&lt;b&gt;JavaScript 엔진&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이 다릅니다:&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Internet Explorer&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: Chakra&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Chrome&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: V8&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Safari&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: JavaScriptCore&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Firefox&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: SpiderMonkey&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Edge&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: V8&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Node.js&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: V8&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;표준 규격: ECMAScript&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;JavaScript는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;ECMAScript&lt;/b&gt;&lt;/span&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;ECMAScript는 버전별로 새로운 기능과 개선 사항이 추가되며, 이에 대한 변경 사항은 &lt;/span&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/ECMAScript&quot;&gt;&lt;span&gt;ECMAScript 위키&lt;/span&gt;&lt;/a&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;&lt;b&gt;JavaScript는 어떻게 공부해야 할까?&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;1. JavaScript는 프로그래밍 언어이다&lt;/b&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;2. 외부 환경과의 상호작용&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;JavaScript는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;브라우저&lt;/b&gt;&lt;/span&gt;&lt;span&gt;와 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Node.js&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 환경에서 동작하며, 각각 &lt;/span&gt;&lt;span&gt;&lt;b&gt;외부 API와 라이브러리&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 사용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;프론트엔드&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 웹 개발 시 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Web APIs&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에 대한 이해가 필요합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;백엔드 (Node.js)&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: Node.js 환경에서 제공하는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Node.js APIs&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 학습해야 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;기초 없이 다음 단계로 넘어가면 큰일 납니다. 특히 초반에 많은 내용을 건너뛰고 심화된 내용을 공부하는 것은 피해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&lt;hr data-ke-style=&quot;style1&quot; /&gt;&lt;/div&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;1. 기초 내용&lt;/b&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;목표&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 기본 문법과 사용법을 학습하고 개발자처럼 생각하는 법을 익힙니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;주요 개념&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;변수 선언: &lt;/span&gt;&lt;span&gt;let&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;const&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;조건문과 반복문: &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;switch&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;while&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;함수와 객체: &lt;/span&gt;&lt;span&gt;function&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;object&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&lt;b&gt;2. 심화 내용&lt;/b&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;목표&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 내부 구현과 고급 개념을 학습하여 기술 면접 대비 및 개발 역량을 강화합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;주요 개념&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;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;Prototype&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 프로토타입 기반 상속 이해&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Hoisting&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 변수와 함수 선언의 실행 흐름&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Scope&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 변수의 범위와 유효성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Closure&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 함수와 렉시컬 스코프 활용&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/JavaScript</category>
      <category>javascritp</category>
      <category>개발 기초</category>
      <category>자바스크립트</category>
      <category>프론트엔드</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/103</guid>
      <comments>https://nicksoon.tistory.com/entry/JavaScript-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%99%80-Nodejs%EC%97%90%EC%84%9C-%EB%8F%99%EC%9E%91%ED%95%98%EB%8A%94-%EA%B0%80%EC%9E%A5-%EB%A7%8E%EC%9D%B4-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%96%B8%EC%96%B4#entry103comment</comments>
      <pubDate>Sun, 15 Dec 2024 23:21:09 +0900</pubDate>
    </item>
    <item>
      <title>네이버 오픈 API 사용 개선 경험 공유</title>
      <link>https://nicksoon.tistory.com/entry/%EB%84%A4%EC%9D%B4%EB%B2%84-%EC%98%A4%ED%94%88-API-%EC%82%AC%EC%9A%A9-%EA%B0%9C%EC%84%A0-%EA%B2%BD%ED%97%98-%EA%B3%B5%EC%9C%A0</link>
      <description>&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;오늘은 &lt;/span&gt;&lt;span&gt;&lt;b&gt;네이버 오픈 API&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 사용하여 쇼핑 정보를 가져오면서 겪었던 문제와 이를 해결했던 경험을 공유하려고 합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 과정에서 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Too Many Requests&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 에러를 해결하고 효율적인 데이터 요청 방법을 찾았던 내용을 소개해 드릴게요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;문제 상황: Too Many Requests&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;span&gt;&lt;b&gt;한 번에 2000개의 키워드&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에 대해 쇼핑 정보를 불러와야 하는 상황이었습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;네이버 오픈 API를 사용해 많은 데이터를 받아오려고 &lt;/span&gt;&lt;span&gt;&lt;b&gt;여러 번 요청&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 보냈지만, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그럴 때마다 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Too Many Requests&lt;/b&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;처음에는 &quot;왜 이런 문제가 발생할까?&quot;라고 고민했습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;당시 요청 방식은 &lt;/span&gt;&lt;span&gt;&lt;b&gt;1초에 상품 100개씩, 키워드 100개&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 요청하는 구조였는데, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;네이버 API는 이러한 대량의 요청을 한 번에 처리하기 어려웠던 것입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;결국 네이버도 API 트래픽이 많이 발생하면 부담이 되겠죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; 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;API 키 사용 구조&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: API 키 하나로 &lt;/span&gt;&lt;span&gt;&lt;b&gt;10,000번 요청&lt;/b&gt;&lt;/span&gt;&lt;span&gt;한 후, 다음 키로 넘어가는 구조였습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;요청 데이터 크기&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 상품 정보를 &lt;/span&gt;&lt;span&gt;&lt;b&gt;100개&lt;/b&gt;&lt;/span&gt;&lt;span&gt;씩 요청했습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;요청 빈도&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;&lt;b&gt;1초에 100개 키워드&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에 대한 요청을 보냈습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이렇게 요청을 보내면 결국 API 서버에 많은 부하가 가게 되어, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;Too Many Requests&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 에러가 발생하게 된 것이죠. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;한동안 API를 사용하지 않고 문제를 해결할 방법을 고민했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 3 []&quot; 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;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;API 키 순차 사용&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 이전에는 API 키 하나로 10,000번 요청한 후에야 다음 키를 사용했지만, &lt;br /&gt;이제는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;API 키를 한 번 사용하면 바로 다음 키로 전환&lt;/b&gt;&lt;/span&gt;&lt;span&gt;하는 방식으로 변경했습니다. &lt;br /&gt;이를 위해 &lt;/span&gt;&lt;span&gt;&lt;b&gt;30개 이상의 API 키&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 준비하고 순차적으로 사용했습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;요청 데이터 크기 조정&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 상품 정보를 &lt;/span&gt;&lt;span&gt;&lt;b&gt;100개씩&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 받는 대신, &lt;/span&gt;&lt;span&gt;&lt;b&gt;10개씩&lt;/b&gt;&lt;/span&gt;&lt;span&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;span&gt;: &lt;/span&gt;&lt;span&gt;&lt;b&gt;1초에 100개 키워드&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에 대해 요청을 보내는 빈도는 유지했습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이렇게 개선된 방식으로 요청을 보냈고, 이전보다 &lt;/span&gt;&lt;span&gt;&lt;b&gt;더 빠르게 데이터를 받을 수 있었습니다&lt;/b&gt;&lt;/span&gt;&lt;span&gt;. 무엇보다 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Too Many Requests&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 에러 없이 안정적으로 데이터를 수집할 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1840&quot; data-origin-height=&quot;685&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Lwe0a/btsK78lQkns/cd0MNsT3KvRhfPVMsRrutK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Lwe0a/btsK78lQkns/cd0MNsT3KvRhfPVMsRrutK/img.png&quot; data-alt=&quot;요청 방식&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Lwe0a/btsK78lQkns/cd0MNsT3KvRhfPVMsRrutK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLwe0a%2FbtsK78lQkns%2Fcd0MNsT3KvRhfPVMsRrutK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1840&quot; height=&quot;685&quot; data-origin-width=&quot;1840&quot; data-origin-height=&quot;685&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;요청 방식&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; 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;span&gt;&lt;b&gt;카페24에서 제공하는 서버&lt;/b&gt;&lt;/span&gt;&lt;span&gt;였기 때문에, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;Redis&lt;/b&gt;&lt;/span&gt;&lt;span&gt;와 같은 고급 캐시 관리 도구를 사용할 수 없었습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 저는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;.txt 파일&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 활용해 &lt;/span&gt;&lt;span&gt;&lt;b&gt;순번을 저장&lt;/b&gt;&lt;/span&gt;&lt;span&gt;하고, &lt;/span&gt;&lt;span&gt;&lt;b&gt;n분의 1&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 방식으로 동작하도록 구현했습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;(참, 저는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;n분의 1&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 방식을 정말 좋아하는 것 같네요  )&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 방식으로 순차적으로 API 키를 관리하며 안정적으로 데이터를 가져올 수 있었고, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;네이버 API의 요청 제한을 효율적으로 피할 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; 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;이번 경험을 통해 대량의 데이터를 API를 통해 가져올 때, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;요청 빈도와 데이터 크기를 적절히 조절하는 것이 중요하다&lt;/b&gt;&lt;/span&gt;&lt;span&gt;는 것을 다시 한 번 느꼈습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;네이버 오픈 API를 사용할 때에도 API 요청에 대한 부담을 줄이고, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;여러 API 키를 순차적으로 활용하여 안정적인 데이터 수집이 가능했습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;여러분도 API 사용 시 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Too Many Requests&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 문제가 발생한다면, &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;요청 빈도와 데이터 크기를 조정하고, &lt;/span&gt;&lt;/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-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;읽어주셔서 감사합니다.  &lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>api요청관리</category>
      <category>api최적화</category>
      <category>toomanyrequests</category>
      <category>네이버API</category>
      <category>데이터수집</category>
      <category>서비스개발경험</category>
      <category>웹개발팁</category>
      <category>웹서비스최적화</category>
      <category>프론트엔드개발</category>
      <category>효율적데이터처리</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/102</guid>
      <comments>https://nicksoon.tistory.com/entry/%EB%84%A4%EC%9D%B4%EB%B2%84-%EC%98%A4%ED%94%88-API-%EC%82%AC%EC%9A%A9-%EA%B0%9C%EC%84%A0-%EA%B2%BD%ED%97%98-%EA%B3%B5%EC%9C%A0#entry102comment</comments>
      <pubDate>Fri, 6 Dec 2024 12:59:28 +0900</pubDate>
    </item>
    <item>
      <title>웹 페이지 최적화 과정: 크롬 Lighthouse 사용 경험 공유</title>
      <link>https://nicksoon.tistory.com/entry/%EC%9B%B9-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%B5%9C%EC%A0%81%ED%99%94-%EA%B3%BC%EC%A0%95-%ED%81%AC%EB%A1%AC-Lighthouse-%EC%82%AC%EC%9A%A9-%EA%B2%BD%ED%97%98-%EA%B3%B5%EC%9C%A0</link>
      <description>&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;안녕하세요. 오늘은 &lt;/span&gt;&lt;span&gt;&lt;b&gt;크롬 Lighthouse&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 사용하여 웹 페이지의 성능을 최적화한 경험을 공유하려고 합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이전에 웹 페이지의 로딩 속도를 &lt;/span&gt;&lt;span&gt;&lt;b&gt;3분에서 3초로 단축&lt;/b&gt;&lt;/span&gt;&lt;span&gt;한 경험을 공유한 적이 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;하지만 그때에도 &quot;정말? 어떻게? 결과는?&quot;이라는 의문이 남아 있었습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그래서 저는 크롬의 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Lighthouse&lt;/b&gt;&lt;/span&gt;&lt;span&gt;라는 훌륭한 도구를 사용하게 되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;Lighthouse 사용 방법&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Lighthouse는 크롬 개발자 도구에서 사용 가능한 성능 측정 도구입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;F12(개발자 도구)&lt;/b&gt;를 열고 오른쪽 &lt;/span&gt;&lt;span&gt;&lt;b&gt;&amp;gt;&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 버튼을 누르면 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Lighthouse&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 탭이 보입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;78&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgOKUk/btsK7ItlPbt/8u1ONCVrXVfRuopngLwynK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgOKUk/btsK7ItlPbt/8u1ONCVrXVfRuopngLwynK/img.png&quot; data-alt=&quot;개발자도구 상단&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgOKUk/btsK7ItlPbt/8u1ONCVrXVfRuopngLwynK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgOKUk%2FbtsK7ItlPbt%2F8u1ONCVrXVfRuopngLwynK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;486&quot; height=&quot;78&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;78&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;개발자도구 상단&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;181&quot; data-origin-height=&quot;278&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/duAbn0/btsK7Ej9Gwk/YO9fipsTdBVNZm9IU5w1vK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/duAbn0/btsK7Ej9Gwk/YO9fipsTdBVNZm9IU5w1vK/img.png&quot; data-alt=&quot;개발자도구 더보기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/duAbn0/btsK7Ej9Gwk/YO9fipsTdBVNZm9IU5w1vK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FduAbn0%2FbtsK7Ej9Gwk%2FYO9fipsTdBVNZm9IU5w1vK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;181&quot; height=&quot;278&quot; data-origin-width=&quot;181&quot; data-origin-height=&quot;278&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;개발자도구 더보기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;여기서 &lt;/span&gt;&lt;span&gt;&lt;b&gt;모바일&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 또는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;데스크톱&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 환경을 선택해 페이지 성능을 검사할 수 있습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;저희 서비스는 &lt;/span&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;669&quot; data-origin-height=&quot;456&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JfeVy/btsK83JJoJk/ujkUkynZYK32tzquMSGM60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JfeVy/btsK83JJoJk/ujkUkynZYK32tzquMSGM60/img.png&quot; data-alt=&quot;크롬 Lighthouse&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JfeVy/btsK83JJoJk/ujkUkynZYK32tzquMSGM60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJfeVy%2FbtsK83JJoJk%2FujkUkynZYK32tzquMSGM60%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;669&quot; height=&quot;456&quot; data-origin-width=&quot;669&quot; data-origin-height=&quot;456&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;크롬 Lighthouse&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; 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;처음 Lighthouse로 측정했을 때, 페이지 로딩 속도는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;3.6초&lt;/b&gt;&lt;/span&gt;&lt;span&gt;였습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;시각적으로 로딩 과정을 확인할 수 있었지만, &lt;/span&gt;&lt;span&gt;&lt;b&gt;Performance&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 점수는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;100점 만점에 34점&lt;/b&gt;&lt;/span&gt;&lt;span&gt;으로 매우 낮은 결과가 나왔습니다. 어느 정도 낮을 것이라고 예상은 했지만, 34점은 생각보다 많이 낮아서 어떻게 개선해야 할지 고민이 되었습니다.&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;757&quot; data-origin-height=&quot;828&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FodLN/btsK7Kq7ed1/4AD8aMGoM6OMBYayO1M4O1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FodLN/btsK7Kq7ed1/4AD8aMGoM6OMBYayO1M4O1/img.png&quot; data-alt=&quot;Lighthouse 리포트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FodLN/btsK7Kq7ed1/4AD8aMGoM6OMBYayO1M4O1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFodLN%2FbtsK7Kq7ed1%2F4AD8aMGoM6OMBYayO1M4O1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;757&quot; height=&quot;828&quot; data-origin-width=&quot;757&quot; data-origin-height=&quot;828&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Lighthouse 리포트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; 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;Lighthouse는 개선해야 할 부분에 대한 설명도 함께 제공해줍니다. &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;h4 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;원인 1: FCP 속도 개선&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt; FCP(First Contentful Paint)&lt;/b&gt; 의 속도가 &lt;/span&gt;&lt;span&gt;&lt;b&gt;3.6초&lt;/b&gt;&lt;/span&gt;&lt;span&gt;로 측정되었습니다. 3.6초가 엄청나게 느린 것은 아니었지만, 조금 더 빠르게 개선할 수 있는 방법이 있지 않을까 생각했습니다. 기존 데이터 가져오는 방식을 &lt;/span&gt;&lt;span&gt;&lt;b&gt;건별 요청&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에서 &lt;/span&gt;&lt;span&gt;&lt;b&gt;한 번에 묶어 요청&lt;/b&gt;&lt;/span&gt;&lt;span&gt;하는 방식으로 수정하여 통신 효율을 높였습니다. 이로 인해 &lt;/span&gt;&lt;span&gt;&lt;b&gt;FCP&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 속도가 &lt;/span&gt;&lt;span&gt;&lt;b&gt;1.4초 ~ 1.6초&lt;/b&gt;&lt;/span&gt;&lt;span&gt;로 크게 개선되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1559&quot; data-origin-height=&quot;629&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bb1DRd/btsK800x9Dc/vgslXyoSeh5qTUaZYjn8Fk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bb1DRd/btsK800x9Dc/vgslXyoSeh5qTUaZYjn8Fk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bb1DRd/btsK800x9Dc/vgslXyoSeh5qTUaZYjn8Fk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbb1DRd%2FbtsK800x9Dc%2FvgslXyoSeh5qTUaZYjn8Fk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1559&quot; height=&quot;629&quot; data-origin-width=&quot;1559&quot; data-origin-height=&quot;629&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-pm-slice=&quot;1 3 []&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;원인 2: CLS 개선&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt; CLS(Cumulative Layout Shift)&lt;/b&gt; 는 사용자가 페이지를 볼 때 레이아웃이 얼마나 갑작스럽게 변하는지를 나타내는 지표입니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;저희 서비스에서는 데이터를 가져오는 과정이 오래 걸려, 데이터를 미리 보여주지 않고 &lt;/span&gt;&lt;span&gt;&lt;b&gt;로딩 화면&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 먼저 보여주었습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그러다 보니 데이터를 가져온 후 &lt;/span&gt;&lt;span&gt;&lt;b&gt;화면이 깜빡거리며 스크롤이 튀는&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 문제가 발생했습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;당시 &lt;/span&gt;&lt;span&gt;&lt;b&gt;CLS&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 점수는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;0.708&lt;/b&gt;&lt;/span&gt;&lt;span&gt;로 매우 낮았고, 이를 개선하기 위해 몇 가지 조치를 취했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;이미지 크기 고정&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 아이콘 이미지에 &lt;/span&gt;&lt;span&gt;&lt;b&gt;width&lt;/b&gt;&lt;/span&gt;&lt;span&gt;와 &lt;/span&gt;&lt;span&gt;&lt;b&gt;height&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 속성을 추가하여 크기를 고정했습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;UI 안정화&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 메인 레이아웃이 &lt;/span&gt;&lt;span&gt;&lt;b&gt;display: none&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에서 &lt;/span&gt;&lt;span&gt;&lt;b&gt;block&lt;/b&gt;&lt;/span&gt;&lt;span&gt;으로 바뀌는 것을 방지하기 위해, &lt;/span&gt;&lt;span&gt;&lt;b&gt;opacity&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 &lt;/span&gt;&lt;span&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에서 &lt;/span&gt;&lt;span&gt;&lt;b&gt;1&lt;/b&gt;&lt;/span&gt;&lt;span&gt;로 변경하도록 수정했습니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이러한 조치를 통해 &lt;/span&gt;&lt;span&gt;&lt;b&gt;CLS 점수&lt;/b&gt;&lt;/span&gt;&lt;span&gt;가 &lt;/span&gt;&lt;span&gt;&lt;b&gt;0.03&lt;/b&gt;&lt;/span&gt;&lt;span&gt;으로 크게 개선되었고, 최종적으로 &lt;/span&gt;&lt;span&gt;&lt;b&gt;67점&lt;/b&gt;&lt;/span&gt;&lt;span&gt;의 성능 점수를 얻을 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;745&quot; data-origin-height=&quot;832&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VP53j/btsK80zuBpr/lRLp4WaopcOMb3YbR3WCPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VP53j/btsK80zuBpr/lRLp4WaopcOMb3YbR3WCPk/img.png&quot; data-alt=&quot;lighthouse 개선후&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VP53j/btsK80zuBpr/lRLp4WaopcOMb3YbR3WCPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVP53j%2FbtsK80zuBpr%2FlRLp4WaopcOMb3YbR3WCPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;745&quot; height=&quot;832&quot; data-origin-width=&quot;745&quot; data-origin-height=&quot;832&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;lighthouse 개선후&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; 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;span&gt;&lt;b&gt;PHP&lt;/b&gt;&lt;/span&gt;&lt;span&gt;에서 &lt;/span&gt;&lt;span&gt;&lt;b&gt;JavaScript&lt;/b&gt;&lt;/span&gt;&lt;span&gt;로 옮겨, &lt;/span&gt;&lt;span&gt;&lt;b&gt;FCP&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 &lt;/span&gt;&lt;span&gt;&lt;b&gt;1초 이내&lt;/b&gt;&lt;/span&gt;&lt;span&gt;로 줄이는 것을 목표로 하고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이렇게 최적화 과정을 거치면서 웹 페이지 성능을 지속적으로 개선하고 있으며, Lighthouse를 활용한 진단과 개선 작업이 큰 도움이 되었습니다. &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;</description>
      <category>개발/개발 필기</category>
      <category>cls개선</category>
      <category>FCP</category>
      <category>lighthouse</category>
      <category>웹로드속도개선</category>
      <category>웹성능개선</category>
      <category>웹퍼포먼스</category>
      <category>웹페이지최적화</category>
      <category>크롬개발자도구</category>
      <category>퍼포먼스튜닝</category>
      <category>프론트엔드개발</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/101</guid>
      <comments>https://nicksoon.tistory.com/entry/%EC%9B%B9-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%B5%9C%EC%A0%81%ED%99%94-%EA%B3%BC%EC%A0%95-%ED%81%AC%EB%A1%AC-Lighthouse-%EC%82%AC%EC%9A%A9-%EA%B2%BD%ED%97%98-%EA%B3%B5%EC%9C%A0#entry101comment</comments>
      <pubDate>Thu, 5 Dec 2024 13:24:35 +0900</pubDate>
    </item>
    <item>
      <title>tmux 사용</title>
      <link>https://nicksoon.tistory.com/entry/tmux-%EC%82%AC%EC%9A%A9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1. tmux란?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;tmux는 하나의 터미널 안에서 여러 터미널 세션을 실행하고 관리할 수 있게 해주는 유틸리티입니다.&lt;/p&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. tmux new -s myapp의 의미&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;tmux: tmux 명령을 실행.&lt;/li&gt;
&lt;li&gt;new: 새로운 tmux 세션을 시작.&lt;/li&gt;
&lt;li&gt;-s myapp: 세션 이름을 myapp으로 지정.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 명령을 실행하면 myapp이라는 이름의 새로운 세션이 시작되며, 세션 내부에서 일반적으로 명령어를 실행하거나 프로그램을 실행할 수 있습니다.&lt;/p&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. 유용한 tmux 명령&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a. &lt;b&gt;세션에서 분리 (Detach)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1733273840669&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Ctrl + b, d&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;b. &lt;b&gt;현재 세션 확인&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1733273858417&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;tmux list-sessions&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;c. &lt;b&gt;세션에 다시 접속 (Attach)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1733273872101&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;tmux attach -t myapp&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;d. &lt;b&gt;세션 종료&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1733273883595&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;exit&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;e. &lt;b&gt;기존 세션 분리 후 새로운 세션 생성&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1733273897979&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;tmux new -s new_session&lt;/code&gt;&lt;/pre&gt;</description>
      <category>개발/개발 필기</category>
      <category>tmux</category>
      <category>무중단 실행</category>
      <category>배포</category>
      <category>파이썬</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/100</guid>
      <comments>https://nicksoon.tistory.com/entry/tmux-%EC%82%AC%EC%9A%A9#entry100comment</comments>
      <pubDate>Wed, 4 Dec 2024 09:58:42 +0900</pubDate>
    </item>
    <item>
      <title>Recoil을 사용한 상태 관리 경험: 왜 우리는 Recoil을 선택했을까?</title>
      <link>https://nicksoon.tistory.com/entry/Recoil%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%9C-%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC-%EA%B2%BD%ED%97%98-%EC%99%9C-%EC%9A%B0%EB%A6%AC%EB%8A%94-Recoil%EC%9D%84-%EC%84%A0%ED%83%9D%ED%96%88%EC%9D%84%EA%B9%8C</link>
      <description>&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;안녕하세요! 오늘은 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Recoil&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 사용해 리액트 애플리케이션에서 상태 관리를 했던 경험을 공유하려고 합니다. 결합도에 대해 생각해보면, 자료 결합도, 스탬프 결합도, 제어 결합도 등 다양한 결합도들이 있죠. 특히 전역 변수는 외부 결합도로, 뭔가 '좋아 보이지 않는' 그런 느낌이 있어요. 그럼에도 불구하고 리액트에서 상태 관리는 전역 상태가 될 필요는 없지만, Recoil 같은 라이브러리를 사용할 때는 대부분 &lt;/span&gt;&lt;span&gt;&lt;b&gt;전역 상태 관리&lt;/b&gt;&lt;/span&gt;&lt;span&gt;로 하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그렇다면 왜 수많은 상태 관리 방법 중에서 우리는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Recoil&lt;/b&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;h3 data-pm-slice=&quot;1 3 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;Recoil 선택의 이유&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;너무 쉬웠어요&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: Recoil이 처음 나왔을 때 그 사용 방법이 정말 쉬웠습니다. 설정도 간단했고, 상태 관리도 꽤 편리했죠. 그래서 처음 접한 우리 팀도 &quot;이거 좋다, 사용해보자!&quot;라고 쉽게 결정할 수 있었습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;새로운 건 써봐야 제맛&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 솔직히 말해서, &lt;/span&gt;&lt;span&gt;&lt;b&gt;새로운 게 나오면 써봐야 하는&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 그 마음이 가장 컸던 것 같아요. &quot;좋은지 안 좋은지는 나중에 보고, 지금은 일단 써보자!&quot;라는 마음으로 Recoil을 선택하게 되었죠.&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그럼 다른 상태 관리 방법보다 &lt;/span&gt;&lt;span&gt;&lt;b&gt;정말 좋은 건지&lt;/b&gt;&lt;/span&gt;&lt;span&gt;, 아니면 &lt;/span&gt;&lt;span&gt;&lt;b&gt;그냥 아무 생각 없이 쓴 것인지&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 궁금하시죠? 각 상태 관리 방식에는 장단점이 있습니다&lt;/span&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 style=&quot;width: 25.31%;&quot;&gt;상태 관리&lt;/td&gt;
&lt;td style=&quot;width: 39.9613%;&quot;&gt;장점&lt;/td&gt;
&lt;td style=&quot;width: 34.7286%;&quot;&gt;단점&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.31%;&quot;&gt;Local State&lt;/td&gt;
&lt;td style=&quot;width: 39.9613%;&quot;&gt;간단하고 직관적, 상태 관리가 독립적&lt;/td&gt;
&lt;td style=&quot;width: 34.7286%;&quot;&gt;Prop Drilling 문제 발생 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.31%;&quot;&gt;Context API&lt;/td&gt;
&lt;td style=&quot;width: 39.9613%;&quot;&gt;전역 상태 관리 가능, 리액트 내장 기능 사용&lt;/td&gt;
&lt;td style=&quot;width: 34.7286%;&quot;&gt;성능 문제, 여러 컨텍스트가 복잡해질 수 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.31%;&quot;&gt;Recoil&lt;/td&gt;
&lt;td style=&quot;width: 39.9613%;&quot;&gt;쉬운 전역 상태 관리, 간단한 상태 공유&lt;/td&gt;
&lt;td style=&quot;width: 34.7286%;&quot;&gt;추가 학습 필요, 자료나 생태계 제한적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.31%;&quot;&gt;Redux&lt;/td&gt;
&lt;td style=&quot;width: 39.9613%;&quot;&gt;명확한 데이터 흐름, 미들웨어를 통한 비동기 처리 가능&lt;/td&gt;
&lt;td style=&quot;width: 34.7286%;&quot;&gt;많은 보일러플레이트, 코드 복잡도 증가&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.31%;&quot;&gt;MobX&lt;/td&gt;
&lt;td style=&quot;width: 39.9613%;&quot;&gt;자동 반응형 업데이트, 간단한 사용&lt;/td&gt;
&lt;td style=&quot;width: 34.7286%;&quot;&gt;디버깅 어려움, 생태계 부족&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 25.31%;&quot;&gt;Zustand&lt;/td&gt;
&lt;td style=&quot;width: 39.9613%;&quot;&gt;가볍고 간단한 설정, 리액트 방식과 유사&lt;/td&gt;
&lt;td style=&quot;width: 34.7286%;&quot;&gt;기능 제한, 대규모 프로젝트에 비적합&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;각 방식마다 장단점이 있지만, &lt;/span&gt;&lt;span&gt;&lt;b&gt;쉽고 간단하다&lt;/b&gt;&lt;/span&gt;&lt;span&gt;는 점이 우리 팀에 가장 큰 매력이었습니다. 무엇보다 빠르게 작업을 해야 하는 상황에서 Recoil은 정말 좋은 선택이었죠. 물론 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Local State&lt;/b&gt;&lt;/span&gt;&lt;span&gt;도 함께 사용하면서 더욱 강력한 상태 관리가 가능했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;Prop Drilling과 Recoil의 등장&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그럼 왜 Recoil을 사용하게 되었을까요? 리액트를 사용해 보신 분들이라면 모두 &lt;/span&gt;&lt;span&gt;&lt;b&gt;prop으로 값을 전달하는 것&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 아실 겁니다. 컴포넌트를 재사용하기 위해서 컴포넌트를 잘게 쪼개고, 그러다 보면 &lt;/span&gt;&lt;span&gt;&lt;b&gt;props를 계속 전달하는 것&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이 필요해지죠. 그리고 그 값이 필요하지 않은 컴포넌트까지도 props를 전달해야 하는 상황이 발생합니다. 이게 바로 유명한 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Prop Drilling&lt;/b&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;한 컴포넌트에서 자식 컴포넌트로, 또 그 아래로, 그 아래로&amp;hellip; 이 과정을 반복하다 보면 코드가 끝도 없이 복잡해집니다. 한 번 변경하려고 하면 값을 여기저기서 리턴하고 또 리턴해야 하고, 글로 쓰기만 해도 머리가 아파옵니다. 이런 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Prop Drilling&lt;/b&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-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이때 등장한 것이 바로 &lt;/span&gt;&lt;span&gt;&lt;b&gt;Recoil&lt;/b&gt;&lt;/span&gt;&lt;span&gt;입니다. Recoil을 사용하면 상태를 전역으로 관리할 수 있어 &lt;/span&gt;&lt;span&gt;&lt;b&gt;중간 컴포넌트가 불필요하게 값을 전달할 필요가 없고&lt;/b&gt;&lt;/span&gt;&lt;span&gt;, 사용하지 않는 컴포넌트도 props를 물고 있을 이유가 없습니다. 전역 상태를 통해 필요한 컴포넌트에서만 값을 구독하고 사용하면 되는 거죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; 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;b&gt;작업의 효율성&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이 높아졌고, prop의 스트레스에서 &lt;/span&gt;&lt;span&gt;&lt;b&gt;해방&lt;/b&gt;&lt;/span&gt;&lt;span&gt;될 수 있었습니다. 개발자라면 다들 아시겠지만, prop 때문에 발생하는 문제에서 벗어나는 건 정말 큰 해방감이에요. 덕분에 우리는 더 빠르고 깔끔하게 작업할 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;Recoil 간단 예시&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Recoil을 이해하기 위해 간단한 예시를 살펴보겠습니다. 다음은 리액트 애플리케이션에서 Recoil을 사용해 &lt;/span&gt;&lt;span&gt;&lt;b&gt;카운터 상태&lt;/b&gt;&lt;/span&gt;&lt;span&gt;를 관리하는 코드입니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1733193892266&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 { RecoilRoot, atom, useRecoilState } from 'recoil';

// 전역 상태 정의 (atom)
const counterState = atom({
  key: 'counterState', // 각 atom은 고유한 키를 가져야 합니다.
  default: 0, // 초기값
});

function Counter() {
  const [count, setCount] = useRecoilState(counterState);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Counter: {count}&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setCount(count + 1)}&amp;gt;Increment&amp;lt;/button&amp;gt;
      &amp;lt;button onClick={() =&amp;gt; setCount(count - 1)}&amp;gt;Decrement&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

function App() {
  return (
    &amp;lt;RecoilRoot&amp;gt;
      &amp;lt;Counter /&amp;gt;
    &amp;lt;/RecoilRoot&amp;gt;
  );
}

export default App;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 예시에서는 &lt;/span&gt;&lt;span&gt;counterState&lt;/span&gt;&lt;span&gt;라는 **전역 상태(atom)**를 정의하고, 이를 &lt;/span&gt;&lt;span&gt;useRecoilState&lt;/span&gt;&lt;span&gt; 훅을 통해 사용하고 있습니다. &lt;/span&gt;&lt;span&gt;RecoilRoot&lt;/span&gt;&lt;span&gt;로 애플리케이션을 감싸 전역 상태가 모든 하위 컴포넌트에서 접근 가능하도록 설정합니다. &lt;/span&gt;&lt;span&gt;&lt;b&gt;카운터 컴포넌트&lt;/b&gt;&lt;/span&gt;&lt;span&gt;는 &lt;/span&gt;&lt;span&gt;counterState&lt;/span&gt;&lt;span&gt;를 구독하고, 버튼을 통해 상태를 업데이트할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; 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;Recoil은 쉽고, 간단하고, 무엇보다 &lt;/span&gt;&lt;span&gt;&lt;b&gt;빠른 작업&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이 필요했던 저희 팀의 요구를 충족시켜 준 도구였습니다. 물론 모든 상황에서 Recoil이 정답은 아닐 수 있지만, 저희 팀이 겪었던 문제를 해결하고 효율적으로 작업을 마칠 수 있도록 도와준 훌륭한 도구였다고 생각합니다.&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;여러분도 Prop Drilling 문제로 고생하고 계신다면, Recoil 한번 써보시는 건 어떨까요? 감사합니다!&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>DeveloperExperience</category>
      <category>FrontendDevelopment</category>
      <category>frontendtips</category>
      <category>Javascript</category>
      <category>propdrilling</category>
      <category>react</category>
      <category>reactstate</category>
      <category>recoil</category>
      <category>statemanagement</category>
      <category>webdevelopment</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/98</guid>
      <comments>https://nicksoon.tistory.com/entry/Recoil%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%9C-%EC%83%81%ED%83%9C-%EA%B4%80%EB%A6%AC-%EA%B2%BD%ED%97%98-%EC%99%9C-%EC%9A%B0%EB%A6%AC%EB%8A%94-Recoil%EC%9D%84-%EC%84%A0%ED%83%9D%ED%96%88%EC%9D%84%EA%B9%8C#entry98comment</comments>
      <pubDate>Tue, 3 Dec 2024 11:46:59 +0900</pubDate>
    </item>
    <item>
      <title>JavaScript에 재미있는 현상</title>
      <link>https://nicksoon.tistory.com/entry/JavaScript%EC%97%90-%EC%9E%AC%EB%AF%B8%EC%9E%88%EB%8A%94-%ED%98%84%EC%83%81</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;미디엄 블로그를 보다가&lt;/p&gt;
&lt;h1 id=&quot;2c41&quot; style=&quot;background-color: #ffffff; color: #242424; text-align: start;&quot; data-selectable-paragraph=&quot;&quot; data-testid=&quot;storyTitle&quot;&gt;Why 1==1 is true but 128==128 is false in Java&amp;nbsp;&lt;/h1&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&amp;nbsp; 자료형 integer는 -128 부터 127 까지라 안된다고 하네요 그래서 .equals()를 사용하라고 하네요&lt;/p&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;우선 ! JavaScript에서도 흥미로운 동작이 발생하지만, Java처럼 명시적인 캐싱 메커니즘은 없습니다.(아쉽)&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;
&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;숫자 비교 (== vs ===)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript는 == 연산자와 === 연산자가 다르게 동작합니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;==는 &lt;b&gt;느슨한 동등 비교&lt;/b&gt;로, 타입 변환을 시도합니다.&lt;/li&gt;
&lt;li&gt;===는 &lt;b&gt;엄격한 동등 비교&lt;/b&gt;로, 타입 변환 없이 값과 타입을 모두 비교합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1733117271556&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(128 == &quot;128&quot;);  // true (타입 변환 발생)
console.log(128 === &quot;128&quot;); // false (타입과 값이 다름)&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. &lt;b&gt;NaN과 NaN 비교&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript에서 NaN은 &quot;숫자가 아님(Not a Number)&quot;을 나타내는 특수 값입니다. 놀랍게도 NaN은 자기 자신과도 같지 않다고 평가됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1733117301592&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true (ECMAScript 6+에서 도입된 안전한 비교)&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;style5&quot; /&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;객체와 프리미티브를 비교할 때, 객체는 내부적으로 &lt;b&gt;프리미티브 값으로 변환&lt;/b&gt;됩니다. 이로 인해 예상치 못한 결과가 나올 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1733117320758&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log([] == 0); // true (빈 배열이 숫자 0으로 변환)
console.log([] == &quot;&quot;); // true (빈 배열이 빈 문자열로 변환)
console.log([1, 2] == &quot;1,2&quot;); // true (배열이 문자열로 변환)&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;4. &lt;b&gt;null과 undefined&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;null과 undefined는 느슨한 동등 비교 시 같은 값으로 평가되지만, 엄격한 동등 비교에서는 다릅니다.&lt;/p&gt;
&lt;pre id=&quot;code_1733117352352&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(null == undefined); // true
console.log(null === undefined); // false&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;5. &lt;b&gt;객체 참조 비교&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript에서 객체를 비교할 때는 **참조(reference)**를 비교합니다. 두 객체가 같은 내용이라도 참조가 다르면 false가 나옵니다.&lt;/p&gt;
&lt;pre id=&quot;code_1733117373084&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const obj1 = { value: 128 };
const obj2 = { value: 128 };
console.log(obj1 == obj2);  // false (다른 참조)
console.log(obj1 === obj2); // false (다른 참조)

const obj3 = obj1;
console.log(obj1 === obj3); // true (같은 참조)&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;6. &lt;b&gt;Object.is와의 비교&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ECMAScript 6에서는 **Object.is**를 통해 엄격한 동등 비교(===)보다 더 직관적인 비교를 할 수 있습니다. 예를 들어, 0과 -0은 ===로 같지만, Object.is로는 다르게 평가됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1733117391394&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(0 === -0);       // true
console.log(Object.is(0, -0)); // false
console.log(Object.is(NaN, NaN)); // true&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;JavaScript 를 다룬다면 한번은 본 내용이지만 또 예외처리 할 때 매우 중요하지만 빼먹더라고요&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 필기겸 다시 기록해 봅니다&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>javascript 객체와 프리미티브</category>
      <category>javascript 기초</category>
      <category>javascript 동작 원리</category>
      <category>JavaScript 비교 연산자</category>
      <category>javascript 오류 이해하기</category>
      <category>javascript 재미있는 현상</category>
      <category>javascript 타입 변환</category>
      <category>느슨한 동등 비교</category>
      <category>엄격한 동등 비교</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/97</guid>
      <comments>https://nicksoon.tistory.com/entry/JavaScript%EC%97%90-%EC%9E%AC%EB%AF%B8%EC%9E%88%EB%8A%94-%ED%98%84%EC%83%81#entry97comment</comments>
      <pubDate>Mon, 2 Dec 2024 14:32:44 +0900</pubDate>
    </item>
    <item>
      <title>효율적인 배열 비교: Set을 사용해 코드 개선하기 처음에는 조금 복잡하게 코드를 작성했지만, 개선을 통해 훨씬 깔끔하고 효율적인 코드로 만들 수 있었어요. 이 과정을 함께 살펴볼까요?</title>
      <link>https://nicksoon.tistory.com/entry/%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9D%B8-%EB%B0%B0%EC%97%B4-%EB%B9%84%EA%B5%90-Set%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%B4-%EC%BD%94%EB%93%9C-%EA%B0%9C%EC%84%A0%ED%95%98%EA%B8%B0-%EC%B2%98%EC%9D%8C%EC%97%90%EB%8A%94-%EC%A1%B0%EA%B8%88-%EB%B3%B5%EC%9E%A1%ED%95%98%EA%B2%8C-%EC%BD%94%EB%93%9C%EB%A5%BC-%EC%9E%91%EC%84%B1%ED%96%88%EC%A7%80%EB%A7%8C-%EA%B0%9C%EC%84%A0%EC%9D%84-%ED%86%B5%ED%95%B4-%ED%9B%A8%EC%94%AC-%EA%B9%94%EB%81%94%ED%95%98%EA%B3%A0-%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9D%B8-%EC%BD%94%EB%93%9C%EB%A1%9C-%EB%A7%8C%EB%93%A4-%EC%88%98-%EC%9E%88%EC%97%88%EC%96%B4%EC%9A%94-%EC%9D%B4-%EA%B3%BC%EC%A0%95%EC%9D%84-%ED%95%A8%EA%BB%98-%EC%82%B4%ED%8E%B4%EB%B3%BC%EA%B9%8C%EC%9A%94</link>
      <description>&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;안녕하세요! 오늘은 두 배열을 비교할 때 효율적으로 코드를 작성하는 방법에 대해 공유하려고 합니다. 처음에는 조금 복잡하게 코드를 작성했지만, 개선을 통해 훨씬 깔끔하고 효율적인 코드로 만들 수 있었어요. 이 과정을 함께 살펴볼까요?&lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;초기 코드&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;처음 작성한 코드는 두 배열을 비교하면서 키워드의 위치를 확인하는 작업이었는데요, 아래와 같았습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1732761350000&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 데이터를 순회하며 keywords 배열과 비교
data.forEach(item =&amp;gt; {
    if (keywords.includes(item.keyword)) {
        // 특정 값의 인덱스 찾기
        const index = keywords.indexOf(item.keyword);
        // 이후 작업
    }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이 코드에서는 &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt; 배열을 &lt;/span&gt;&lt;span&gt;forEach&lt;/span&gt;&lt;span&gt;로 한 번 순회하고, 각 항목마다 &lt;/span&gt;&lt;span&gt;keywords&lt;/span&gt;&lt;span&gt; 배열에서 값을 찾기 위해 &lt;/span&gt;&lt;span&gt;includes&lt;/span&gt;&lt;span&gt;와 &lt;/span&gt;&lt;span&gt;indexOf&lt;/span&gt;&lt;span&gt;를 사용했어요.&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;즉, &lt;/span&gt;&lt;span&gt;data&lt;/span&gt;&lt;span&gt; 배열을 순회하는 중에 &lt;/span&gt;&lt;span&gt;keywords&lt;/span&gt;&lt;span&gt; 배열을 매번 검색하게 되어, 반복 작업이 겹치면서 비효율적으로 보였습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;개선된 코드&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;위의 문제를 해결하기 위해, &lt;/span&gt;&lt;span&gt;Set&lt;/span&gt;&lt;span&gt; 자료 구조를 활용해 개선해 보았습니다. &lt;/span&gt;&lt;span&gt;Set&lt;/span&gt;&lt;span&gt;은 검색 속도가 빠르기 때문에 더 효율적으로 작업할 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1732761389532&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// keywords 배열을 Set으로 변환
const keywordSet = new Set(keywords);

// data 배열을 순회하며 Set을 통해 키워드 존재 여부를 확인
data.forEach((item, index) =&amp;gt; {
    if (keywordSet.has(item.keyword)) {
        console.log(`매칭된 항목 (인덱스: ${index}):`, item);
    }
});&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 3 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;개선된 코드 설명&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;Set&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; 사용&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;keywords&lt;/span&gt;&lt;span&gt; 배열을 &lt;/span&gt;&lt;span&gt;Set&lt;/span&gt;&lt;span&gt;으로 변환하여 키워드의 존재 여부를 빠르게 확인할 수 있도록 했습니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;효율적인 검색&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: &lt;/span&gt;&lt;span&gt;keywordSet.has(item.keyword)&lt;/span&gt;&lt;span&gt;를 사용하여 키워드의 존재 여부를 확인하므로, &lt;/span&gt;&lt;span&gt;includes&lt;/span&gt;&lt;span&gt;와 &lt;/span&gt;&lt;span&gt;indexOf&lt;/span&gt;&lt;span&gt;를 사용하는 것보다 더 효율적입니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;반복 횟수 감소&lt;/b&gt;&lt;/span&gt;&lt;span&gt;: 이전 코드에서는 내부에서 여러 번 배열을 검색하는 작업이 있었지만, &lt;/span&gt;&lt;span&gt;Set&lt;/span&gt;&lt;span&gt;을 사용하면 검색이 더 간단해지고 반복 횟수가 줄어듭니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-pm-slice=&quot;1 5 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;결과&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;true&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;초기 코드&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&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;data.forEach&lt;/span&gt;&lt;span&gt;: 1번 반복&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;keywords.includes&lt;/span&gt;&lt;span&gt;: 각 데이터마다 검색 (최악의 경우 &lt;/span&gt;&lt;span&gt;keywords&lt;/span&gt;&lt;span&gt; 전체를 탐색)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;keywords.indexOf&lt;/span&gt;&lt;span&gt;: 각 데이터마다 인덱스 검색&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;개선된 코드&lt;/b&gt;&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;
&lt;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;data.forEach&lt;/span&gt;&lt;span&gt;: 1번 반복&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;keywordSet.has&lt;/span&gt;&lt;span&gt;: 각 데이터마다 &lt;/span&gt;&lt;span&gt;Set&lt;/span&gt;&lt;span&gt;에서 키워드 존재 여부를 확인&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이렇게 변경한 후 코드는 더 깔끔해졌고, 반복 횟수도 줄어들어 효율성이 개선되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;마무리&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;개발을 하다 보면, 처음에는 기능적으로 동작하게 만들지만, 시간이 지나면서 점점 코드의 효율성과 가독성을 개선해야 할 필요를 느끼게 됩니다. 이번 경우에도 &lt;/span&gt;&lt;span&gt;Set&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;</description>
      <category>개발/개발 필기</category>
      <category>Javascript</category>
      <category>javascript효율성</category>
      <category>set사용법</category>
      <category>배열비교</category>
      <category>웹개발</category>
      <category>코드개선</category>
      <category>코딩팁</category>
      <category>프론트엔드개발</category>
      <category>효율적인코드작성</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/96</guid>
      <comments>https://nicksoon.tistory.com/entry/%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9D%B8-%EB%B0%B0%EC%97%B4-%EB%B9%84%EA%B5%90-Set%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%B4-%EC%BD%94%EB%93%9C-%EA%B0%9C%EC%84%A0%ED%95%98%EA%B8%B0-%EC%B2%98%EC%9D%8C%EC%97%90%EB%8A%94-%EC%A1%B0%EA%B8%88-%EB%B3%B5%EC%9E%A1%ED%95%98%EA%B2%8C-%EC%BD%94%EB%93%9C%EB%A5%BC-%EC%9E%91%EC%84%B1%ED%96%88%EC%A7%80%EB%A7%8C-%EA%B0%9C%EC%84%A0%EC%9D%84-%ED%86%B5%ED%95%B4-%ED%9B%A8%EC%94%AC-%EA%B9%94%EB%81%94%ED%95%98%EA%B3%A0-%ED%9A%A8%EC%9C%A8%EC%A0%81%EC%9D%B8-%EC%BD%94%EB%93%9C%EB%A1%9C-%EB%A7%8C%EB%93%A4-%EC%88%98-%EC%9E%88%EC%97%88%EC%96%B4%EC%9A%94-%EC%9D%B4-%EA%B3%BC%EC%A0%95%EC%9D%84-%ED%95%A8%EA%BB%98-%EC%82%B4%ED%8E%B4%EB%B3%BC%EA%B9%8C%EC%9A%94#entry96comment</comments>
      <pubDate>Thu, 28 Nov 2024 11:38:43 +0900</pubDate>
    </item>
    <item>
      <title>프론트엔트 지식 GPT질문</title>
      <link>https://nicksoon.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%ED%8A%B8-%EC%A7%80%EC%8B%9D-GPT%EC%A7%88%EB%AC%B8</link>
      <description>&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;안녕하세요! 오늘은 프론트엔드 지식을 채우기 위해 제가 어떤 식으로 공부하고 있는지, 그리고 GPT에게 받은 도움을 바탕으로 어떻게 정리했는지에 대해 이야기해보려고 합니다. 이직 준비와 프론트엔드 지식 확장을 위해 많이 다루어지는 주제를 찾아보았어요. 많은 사람들이 다루는 주제는 그만큼 중요하고, 프론트엔드 개발자라면 알고 있어야 한다고 생각했거든요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;Q: 구글에서 제일 많은 프론트엔드 블로그 주제 top 10 알려줘&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;이유는 간단해요.&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 많은 사람들이 다루는 주제는 그만큼 인기가 있고, 프론트엔드 개발자라면 반드시 알아야 하는 내용일 가능성이 높다고 생각했기 때문입니다. 그래서 GPT에게 이렇게 물어봤습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-pm-slice=&quot;1 3 []&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span&gt;&lt;b&gt;GPT의 답변&lt;/b&gt;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;1. React의 상태 관리 (State Management)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Redux, MobX, React Context API 등 다양한 상태 관리 도구의 비교와 사용법.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;상태 관리의 모범 사례와 프로젝트 적용 팁.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Redux: &lt;a href=&quot;https://ko.redux.js.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;Redux&lt;/span&gt;&lt;span&gt; 공식&lt;/span&gt;&lt;span&gt; 문서&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;MobX: &lt;a href=&quot;https://ko.mobx.js.org/README.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;MobX&lt;/span&gt;&lt;span&gt; 공식&lt;/span&gt;&lt;span&gt; 문서&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;React Context API: &lt;a href=&quot;https://ko.react.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;React&lt;/span&gt;&lt;span&gt; 공식&lt;/span&gt;&lt;span&gt; 문서&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;2. JavaScript 비동기 처리: async/await, Promise&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;JavaScript의 비동기 처리 방식인 &lt;/span&gt;&lt;span&gt;async/await&lt;/span&gt;&lt;span&gt;과 &lt;/span&gt;&lt;span&gt;Promise&lt;/span&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;JavaScript 비동기 처리: &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous&quot;&gt;&lt;span&gt;MDN&lt;/span&gt;&lt;span&gt; 웹&lt;/span&gt;&lt;span&gt; 문서&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;async/await 가이드: &lt;a href=&quot;https://javascript.info/async-await&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;JavaScript&lt;/span&gt;&lt;span&gt;.info&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;3. CSS Flexbox와 Grid 시스템 완벽 가이드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Flexbox와 Grid 레이아웃을 이용한 반응형 UI 구현 방법.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;둘의 차이점과 실무에서의 활용 사례.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Flexbox 레이아웃: &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout&quot;&gt;&lt;span&gt;MDN&lt;/span&gt;&lt;span&gt; Flexbox&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;CSS Grid 레이아웃: &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/CSS/CSS_grid_layout&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;CSS&lt;/span&gt;&lt;span&gt; Tricks&lt;/span&gt;&lt;span&gt; Grid&lt;/span&gt;&lt;span&gt; 가이드&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;4. 프론트엔드 성능 최적화&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;웹페이지 로딩 속도 개선 방법: Lazy Loading, 코드 스플리팅, 이미지 최적화 등.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;웹 성능 최적화: &lt;a href=&quot;https://web.dev/explore/fast?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;Google&lt;/span&gt;&lt;span&gt; Web&lt;/span&gt;&lt;span&gt;.dev&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;코드 스플리팅과 Lazy Loading: &lt;a href=&quot;https://ko.legacy.reactjs.org/docs/code-splitting.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;React&lt;/span&gt;&lt;span&gt; 공식&lt;/span&gt;&lt;span&gt; 문서&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;5. 웹 접근성 (Accessibility, a11y) 개선하기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;웹 접근성 가이드: &lt;a href=&quot;https://www.w3.org/WAI/fundamentals/accessibility-intro/&quot;&gt;&lt;span&gt;W3C&lt;/span&gt;&lt;span&gt; WAI&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ARIA 사용법: &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA&quot;&gt;&lt;span&gt;MDN&lt;/span&gt;&lt;span&gt; ARIA&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;6. TypeScript로 JavaScript 프로젝트 개선하기&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;TypeScript의 장점과 기존 프로젝트로의 마이그레이션 팁.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;TypeScript 공식 문서: &lt;a href=&quot;https://www.typescriptlang.org/ko/docs/handbook/intro.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;TypeScript&lt;/span&gt;&lt;span&gt; Handbook&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;TypeScript 마이그레이션: &lt;a href=&quot;https://www.typescriptlang.org/ko/docs/handbook/2/basic-types.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;타입스크립트 베이직 - 타입스크립트 공식 문서&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;7. 프론트엔드 테스팅: Jest와 Testing Library 사용법&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Jest 공식 문서: &lt;/span&gt;&lt;span&gt;&lt;a href=&quot;https://jestjs.io/docs/getting-started&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Jest.io&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;React Testing Library: &lt;/span&gt;&lt;span&gt;&lt;a href=&quot;https://testing-library.com/docs/react-testing-library/intro/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Testing Library 문서&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;8. 반응형 디자인을 위한 CSS와 Media Queries&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;반응형 디자인 개념: &lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries&quot;&gt;&lt;span&gt;MDN Media Queries&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;반응형 웹 디자인 소개: &lt;/span&gt;&lt;span&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Learn/CSS/CSS_layout/Responsive_Design&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Smashing Magazine&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;9. 웹팩(Webpack) 기초와 최적화&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;웹팩 공식 문서: &lt;/span&gt;&lt;span&gt;&lt;a href=&quot;https://webpack.kr/concepts/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Webpack.js&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;웹팩 최적화 가이드: &lt;/span&gt;&lt;span&gt;&lt;a href=&quot;https://web.dev/articles/use-long-term-caching?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Google Web.dev&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;10. 프론트엔드 배포 자동화: CI/CD 파이프라인 설정&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;GitHub Actions 공식 문서: &lt;/span&gt;&lt;a href=&quot;https://docs.github.com/en/actions&quot;&gt;&lt;span&gt;GitHub Actions&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;Jenkins 설정: &lt;/span&gt;&lt;span&gt;&lt;a href=&quot;https://www.jenkins.io/doc/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Jenkins 공식 문서&lt;/a&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;style5&quot; /&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이렇게 GPT의 답변을 받아보니 생각보다 일하면서 사용했던 것도 많고, 알고는 있지만 적용하지 못했던 것들, 그리고 당연한 것 같지만 설명을 못했던 부분까지 잘 정리되어 있었어요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; 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;b&gt;원문을 보는 이유&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 저는 블로그가 아닌 원문을 보는 이유가 있어요. 근본적인 내용을 이해해야 확장도 가능하고, 블로그 내용을 보더라도 옳고 그름을 판단할 수 있기 때문이죠. 원문을 보면 저와 비슷한 환경에서 개발한 분들이 어떻게 구현하고 정의했는지 알 수 있어요. 이렇게 해야 문제가 발생하거나 업데이트 후 변경사항이 있을 때도 더 쉽게 대응할 수 있죠.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;(물론 다 공식 문서가 아니에요 ㅋㅋㅋ GPT가 404 페이지나 다른 정보를 알려줘서 다 수정을 했어요)&lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;물론 원문은 영어로 되어 있어서 어렵긴 하지만, 구글 번역기와 파파고가 있으니 저는 편하게 읽고 있습니다.  &lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 물론 이 모든 내용을 다 공부해야겠죠! 면접 준비를 위해서라도 중요한 내용들이고, 이 글을 읽는 분들에게도 좋은 공부 주제가 되었으면 좋겠습니다. 이렇게 제 필기를 마치겠습니다. 하핫  &lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>css레이아웃</category>
      <category>javascript비동기처리</category>
      <category>React상태관리</category>
      <category>typescript마이그레이션</category>
      <category>웹개발블로그</category>
      <category>웹성능최적화</category>
      <category>웹접근성</category>
      <category>프론트엔드개발</category>
      <category>프론트엔드면접</category>
      <category>프론트엔드테스팅</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/95</guid>
      <comments>https://nicksoon.tistory.com/entry/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%ED%8A%B8-%EC%A7%80%EC%8B%9D-GPT%EC%A7%88%EB%AC%B8#entry95comment</comments>
      <pubDate>Tue, 26 Nov 2024 15:28:42 +0900</pubDate>
    </item>
    <item>
      <title>센트리 사용</title>
      <link>https://nicksoon.tistory.com/entry/%EC%84%BC%ED%8A%B8%EB%A6%AC-%EC%82%AC%EC%9A%A9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;안녕하세요! 오늘은 센트리(Sentry)를 사용한 경험을 공유해보려고 합니다. 제가 왜 센트리를 도입하게 되었는지, 그리고 어떻게 사용했는지 이야기해볼게요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;센트리를 사용하게 된 계기&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 어느 날부터 지속적으로 고객들에게서 서비스가 안 된다는 클레임이 들어왔습니다. 문제는 고객들이 정확한 이유를 알려주지는 않는다는 점이었어요. 제 PC에서는 아무 문제가 없었기 때문에 더 답답했죠. 다행히 친절한 고객님들께서 계정 정보를 알려주셔서, 활동한 시간을 추적하며 원인을 추론하고 문제를 해결하긴 했습니다.&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;하지만 문제는 반복되었고, 개선이 되지 않아 정말 답답할 때, 사수로 오신 개발자 분께서 센트리(Sentry)를 추천해주셨습니다. 센트리는 실시간으로 에러를 모니터링하고 알림을 주는 아주 강력한 도구입니다. &lt;/span&gt;&lt;span&gt;Sentry 홈페이지&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;a href=&quot;https://sentry.io/welcome/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://sentry.io/welcome/&lt;/a&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;2358&quot; data-origin-height=&quot;1728&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bjzL91/btsKT5oPdLH/R3YuweI3kEXx51Gy38kZK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bjzL91/btsKT5oPdLH/R3YuweI3kEXx51Gy38kZK0/img.png&quot; data-alt=&quot;센트리 홈페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bjzL91/btsKT5oPdLH/R3YuweI3kEXx51Gy38kZK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbjzL91%2FbtsKT5oPdLH%2FR3YuweI3kEXx51Gy38kZK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;572&quot; height=&quot;419&quot; data-origin-width=&quot;2358&quot; data-origin-height=&quot;1728&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;센트리 홈페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;센트리를 설치하는 방법&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 센트리를 설치하는 방법은 두 가지가 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span&gt;오픈 소스인 센트리를 서버에 직접 설치하는 방법&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;센트리 홈페이지에서 회원가입을 하고, 서비스를 대여하는 방식으로 오류를 수집하는 방법&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;저희는 서버에 도커(Docker)를 사용해 직접 설치하기로 했습니다. 그래도 이 블로그를 보시는 분들 중에는 서버에 도메인까지 연결할 환경이 되지 않는 분들도 있을 수 있으니, 두 번째 방법인 센트리 홈페이지를 통해 사용하는 방법을 나누어 볼게요.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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 data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;1. GET STARTED&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 버튼을 통해 회원가입을 진행합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;198&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rlEds/btsKUfykEq0/5i69HEwryURkSvDM8Kg931/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rlEds/btsKUfykEq0/5i69HEwryURkSvDM8Kg931/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rlEds/btsKUfykEq0/5i69HEwryURkSvDM8Kg931/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrlEds%2FbtsKUfykEq0%2F5i69HEwryURkSvDM8Kg931%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;152&quot; data-origin-width=&quot;828&quot; data-origin-height=&quot;198&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. 회원가입 페이지 (구글, 깃 AZURE? 로도 가입이 가능하다고 합니다)&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;1382&quot; data-origin-height=&quot;1516&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dL4W2Y/btsKTGbQgPy/9IJKrKV9HGsUFhEkc5GbM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dL4W2Y/btsKTGbQgPy/9IJKrKV9HGsUFhEkc5GbM0/img.png&quot; data-alt=&quot;회원가입 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dL4W2Y/btsKTGbQgPy/9IJKrKV9HGsUFhEkc5GbM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdL4W2Y%2FbtsKTGbQgPy%2F9IJKrKV9HGsUFhEkc5GbM0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;502&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;1516&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;회원가입 페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;3. 회원 가입 후&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;b&gt;Create Project&lt;/b&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;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3154&quot; data-origin-height=&quot;1734&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tejRp/btsKT8eMF4k/1Ma31lukblsDLqXG4dXpZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tejRp/btsKT8eMF4k/1Ma31lukblsDLqXG4dXpZ1/img.png&quot; data-alt=&quot;센트리 워크 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tejRp/btsKT8eMF4k/1Ma31lukblsDLqXG4dXpZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtejRp%2FbtsKT8eMF4k%2F1Ma31lukblsDLqXG4dXpZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;260&quot; data-origin-width=&quot;3154&quot; data-origin-height=&quot;1734&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;센트리 워크 페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;4. 프로젝트 언어를 선택합니다 (저는 JavaScript를 선택했어요).&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;2870&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LmOp8/btsKVABgKkJ/Vpr6nlofpjrAgy2iKzF9Tk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LmOp8/btsKVABgKkJ/Vpr6nlofpjrAgy2iKzF9Tk/img.png&quot; data-alt=&quot;센트리 언어 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LmOp8/btsKVABgKkJ/Vpr6nlofpjrAgy2iKzF9Tk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLmOp8%2FbtsKVABgKkJ%2FVpr6nlofpjrAgy2iKzF9Tk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;671&quot; height=&quot;234&quot; data-origin-width=&quot;2870&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;센트리 언어 선택&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;5. 알림을 언제 받을지 선택하는 단계가 나옵니다:&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;1724&quot; data-origin-height=&quot;1022&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zrp1h/btsKTTPNAVz/naigP92gkCBMKUJFEcnHEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zrp1h/btsKTTPNAVz/naigP92gkCBMKUJFEcnHEk/img.png&quot; data-alt=&quot;센트리 알림 옵션, 프로젝트 이름 바꾸기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zrp1h/btsKTTPNAVz/naigP92gkCBMKUJFEcnHEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzrp1h%2FbtsKTTPNAVz%2FnaigP92gkCBMKUJFEcnHEk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1724&quot; height=&quot;1022&quot; data-origin-width=&quot;1724&quot; data-origin-height=&quot;1022&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;센트리 알림 옵션, 프로젝트 이름 바꾸기&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&amp;nbsp;우선순위가 높은 에러부터 알람&lt;/li&gt;
&lt;li&gt;&amp;nbsp;n분 동안 n번의 에러가 발생하면 알람&lt;/li&gt;
&lt;li&gt;&amp;nbsp;나중에 알림 설정&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;저는 편리하게 1번을 선택했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot; data-spread=&quot;true&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;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6. 프레임 워크를 선택을 해 줍니다. 프레임워크가 없거나 유명?하지 않으면 없을 수 있어요&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;1580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dUP9om/btsKUjf44Rc/ekn5163DXycSPTkfhRaMkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dUP9om/btsKUjf44Rc/ekn5163DXycSPTkfhRaMkK/img.png&quot; data-alt=&quot;프레임 워크 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dUP9om/btsKUjf44Rc/ekn5163DXycSPTkfhRaMkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdUP9om%2FbtsKUjf44Rc%2Fekn5163DXycSPTkfhRaMkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;256&quot; height=&quot;496&quot; data-origin-width=&quot;816&quot; data-origin-height=&quot;1580&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;프레임 워크 선택&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;구성하기&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 생성을 완료하면 바로 각 언어에 맞는 구성 방법을 안내받을 수 있습니다. 각 언어마다 설명이 잘 되어 있어서 그대로 따라 하면 쉽게 설정할 수 있어요. 솔직히 말해서, 보고 하나씩 해보면 진짜 쉽습니다. 너무 쉽게 느껴질 수도 있지만, 사실입니다. 정말로요!&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1804&quot; data-origin-height=&quot;1688&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bOgNNn/btsKUhQryBK/Gpa5AbzvIMiXgtj6IbJRY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bOgNNn/btsKUhQryBK/Gpa5AbzvIMiXgtj6IbJRY1/img.png&quot; data-alt=&quot;센트리 설명 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bOgNNn/btsKUhQryBK/Gpa5AbzvIMiXgtj6IbJRY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbOgNNn%2FbtsKUhQryBK%2FGpa5AbzvIMiXgtj6IbJRY1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;481&quot; height=&quot;450&quot; data-origin-width=&quot;1804&quot; data-origin-height=&quot;1688&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;센트리 설명 페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;센트리 사용 후 느낀 점&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 센트리를 설정하고 나서 처음 2주 동안 알림이 정말 많이 왔습니다. 이렇게 오류를 모니터링하면서, 어떤 오류가 발생했는지 바로 확인하고 중요도에 따라 빠르게 수정할 수 있었습니다. 심지어 센트리는 어떤 오류가 발생했는지 영상을 통해 보여주기도 해서, 문제 해결에 큰 도움이 되었어요.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;다음 포스트에서는 또 다른 개발 경험을 나눠보겠습니다. 기대해주세요!&lt;/span&gt;&lt;/p&gt;</description>
      <category>개발/개발 필기</category>
      <category>javascript디버깅</category>
      <category>sentry도입기</category>
      <category>개발자도구</category>
      <category>버그추적</category>
      <category>서비스안정성</category>
      <category>센트리</category>
      <category>에러모니터링</category>
      <category>오블완</category>
      <category>티스토리챌린지</category>
      <category>프로젝트관리</category>
      <author>nicksoon</author>
      <guid isPermaLink="true">https://nicksoon.tistory.com/94</guid>
      <comments>https://nicksoon.tistory.com/entry/%EC%84%BC%ED%8A%B8%EB%A6%AC-%EC%82%AC%EC%9A%A9#entry94comment</comments>
      <pubDate>Sun, 24 Nov 2024 20:04:24 +0900</pubDate>
    </item>
  </channel>
</rss>