<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Developer Turtle-hwan</title>
    <link>https://turtle-hwan.tistory.com/</link>
    <description>흘러가는 생각과 잡념, 공부했던 기록을 붙잡아 놓기 위해 시작합니다

https://github.com/Turtle-Hwan</description>
    <language>ko</language>
    <pubDate>Sat, 4 Jul 2026 06:49:18 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Turtle-hwan</managingEditor>
    <image>
      <title>Developer Turtle-hwan</title>
      <url>https://tistory1.daumcdn.net/tistory/5043531/attach/9f11137a374349f3b04da5fb41703bf7</url>
      <link>https://turtle-hwan.tistory.com</link>
    </image>
    <item>
      <title>기록의 파편화를 세컨드 브레인에 LLM을 붙여 해결하기 - 컨텍스트 단편화와 메모리 단편화(fragmentation)</title>
      <link>https://turtle-hwan.tistory.com/entry/%EA%B8%B0%EB%A1%9D%EC%9D%98-%ED%8C%8C%ED%8E%B8%ED%99%94%EB%A5%BC-%EC%84%B8%EC%BB%A8%EB%93%9C-%EB%B8%8C%EB%A0%88%EC%9D%B8%EC%97%90-LLM%EC%9D%84-%EB%B6%99%EC%97%AC-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%EB%8B%A8%ED%8E%B8%ED%99%94%EC%99%80-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%8B%A8%ED%8E%B8%ED%99%94fragmentation</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;572&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caGqzk/dJMb99Z96vW/25HK4AQzWQniK1JM7Foip1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caGqzk/dJMb99Z96vW/25HK4AQzWQniK1JM7Foip1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caGqzk/dJMb99Z96vW/25HK4AQzWQniK1JM7Foip1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaGqzk%2FdJMb99Z96vW%2F25HK4AQzWQniK1JM7Foip1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;860&quot; height=&quot;480&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;572&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기록의 파편화를 겪은 배경&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;LLM 시대에 맥락이 너무 파편적이다 &amp;rarr; OS에서 메모리 단편화를 어떻게 해결할까? 이를 연결지을 수 있지 않을까? 라는 글감이 떠올랐다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 기록을 찾아보니 2024년 초에 내가 기록해두었던 &amp;ldquo;기록의 파편화&amp;rdquo; 라는 제목의 짧은 글이 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 당시에는 &amp;ldquo;세컨드 브레인&amp;rdquo;이라는 용어를 필두로 옵시디언과 노션을 활용해서 많이, 자주, 다양한 분야를 기록하고 엮어두는 것이 유행이었고 해보았었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 오히려 기록할 곳이 너무 많고 다양해지다보니 기록이 파편화되고, 이를 어떻게 해결해야 할지 고민이 많이 되는 상황이었다. 결국 도메인 별로, 주제 별로 플랫폼을 다르게 쓰는 것으로 해결했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주로 옵시디언은 학교 수업들과 과제 위주로 체계화해서 정리했고 네이버 mybox로 동기화 시켰다. notion은 주로 그때 그때 떠오르는 발상들과 매일매일의 TODO, 회고를 정리해두는 방향으로 썼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옵시디언이 초기에 유명해진 이유도 그래프 형태로 쉽게 보여주는 연결성 덕이 아니었던가 싶어 여기에 notion 링크를 삽입해서 백링크와 링크를 연결해보는 것도 했었다. &lt;s&gt;&lt;span data-token-index=&quot;1&quot;&gt;사람이 일일이 할 것이 못 되어 그만두긴 했지만..&lt;/span&gt; &lt;/s&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;358&quot; data-origin-height=&quot;617&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baLAMh/dJMcadakG0R/lttCjhvhkoaj7AKuXx2j3K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baLAMh/dJMcadakG0R/lttCjhvhkoaj7AKuXx2j3K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baLAMh/dJMcadakG0R/lttCjhvhkoaj7AKuXx2j3K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaLAMh%2FdJMcadakG0R%2FlttCjhvhkoaj7AKuXx2j3K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;200&quot; height=&quot;345&quot; data-origin-width=&quot;358&quot; data-origin-height=&quot;617&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;728&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7Lwq6/dJMcagyahTN/pXVDMMh3RVuOeApzZa13G0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7Lwq6/dJMcagyahTN/pXVDMMh3RVuOeApzZa13G0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7Lwq6/dJMcagyahTN/pXVDMMh3RVuOeApzZa13G0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7Lwq6%2FdJMcagyahTN%2FpXVDMMh3RVuOeApzZa13G0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;200&quot; height=&quot;409&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;728&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-ke-size=&quot;size23&quot;&gt;기록들과 연결된 LLM 맛보기 - AI를 통해 지속 개선하는 루프를 타자&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;21년도부터 노션에 기록하기 시작했으니 벌써 5년치 기록이 쌓였고, 이전 기록들도 정리를 해야 하는데 아무래도 손이 잘 안 가게 되어 이걸 어떻게 해결할까 싶어 고민하던 차에 회사에서 노션 AI를 아주 야무지게 썼던 것이 떠올라 노션 AI에 다 던져봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 정리된 상황이 어떤지, 부족한 것이 어떤지, 앞으로 어떻게 정리하면 좋을지를 생각보다 자세하게 평가하고 알려줘서 놀라웠다. 실제 답변은 아래와 같다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;  현재 습관 분석
✅ 잘하고 있는 것
1. 기록의 양과 솔직함이 뛰어남
2. 회의 내용을 맥락과 함께 기록
3. 체크박스 활용으로 완료/미완료 추적

  개선이 필요한 부분
1. &quot;일지&quot;와 &quot;할 일&quot;과 &quot;메모&quot;가 한 페이지에 전부 섞여 있음
2. 미완료 TODO가 과거 주차에 묻혀서 사라짐
3. 우선순위 표시가 없음
4. 개인 생활과 업무가 한 스트림에 섞여 있음

##   핵심 한 줄 요약
&quot;기록력은 상위 1%인데, 기록을 '다시 꺼내 쓰는 구조'가 없다.&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 바탕으로 claude cowork나 openclaw 등을 이용해 notion과 obsidian을 연결해두고 주기적으로 정리하거나 회고하는 습관을 들여야겠다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uJBDW/dJMcaa5OyCb/GkYdocoidqV66mC2WKUat0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uJBDW/dJMcaa5OyCb/GkYdocoidqV66mC2WKUat0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uJBDW/dJMcaa5OyCb/GkYdocoidqV66mC2WKUat0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuJBDW%2FdJMcaa5OyCb%2FGkYdocoidqV66mC2WKUat0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;360&quot; height=&quot;360&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;메모리 단편화란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 메모리 단편화에 대해 짚고 넘어가보자.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;메모리 단편화는 기억 장치를 쓸수록 정보의 저장되고 삭제되는 크기가 다 다르므로 빈 공간이 점점 여러 개로 나뉘는 현상을 말한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현대에 와서는 상대적으로 여유로운 자원인 디스크(HDD, SSD)보다는 RAM에 초점이 맞추어져&amp;nbsp; &amp;ldquo;메모리&amp;rdquo; 단편화로 용어가 고착된 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;궁금해서 좀 더 찾아보다 보니 글이 너무 길어질 것 같아 자세한 내용은 다음 글에서...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그렇다면 컨텍스트 단편화(Context Fragmentation)란?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 &lt;s&gt;혹시 내가 최초일까 싶어 신나서&lt;/s&gt; 찾아보니 논문과 여러 블로그에서 이미 쓰이는 용어였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리 단편화가 물리적인 공간 낭비와 비효율에 초점이 맞춰져 있다면, 컨텍스트 단편화는 의미(semantic)와 논리적 흐름의 유실에 초점이 맞춰져 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LLM 컨텍스트 한계 때문에 여러 텍스트 덩어리(chunk) 단위로 잘라서 저장하고 대화를 주고받다 보니 앞 뒤 문맥 연결성이 유실되는 것을 뜻한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 이 글에서 말하고자 하는 바처럼, 여러 AI 툴이나 기록 저장용 DB들이 서로 상태와 맥락을 공유하지 못해서 사용자가 매번 배경지식을 새로 입력해주어야 하는 문제를 지칭한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;572&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHSKOJ/dJMcahcMPk4/6jN3gXQhTprsZjXIDxh370/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHSKOJ/dJMcahcMPk4/6jN3gXQhTprsZjXIDxh370/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHSKOJ/dJMcahcMPk4/6jN3gXQhTprsZjXIDxh370/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHSKOJ%2FdJMcahcMPk4%2F6jN3gXQhTprsZjXIDxh370%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;251&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;572&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;컨텍스트 단편화를 어떻게 해결할까&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 AI를 활발하게 쓰는 사람들은 모두 컨텍스트 단편화 문제를 겪고 있다고 생각한다. Slack, Notion, Linear, GitHub에다 각자 개인들이 가지고 있는 맥락까지 기록은 많이 쌓여가지만 그 사이 틈이 점점 많이 생겨나고 전체적인 맥락을 유지하기가 힘든 경험을 많이 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더구나 AI한테 일을 잘 시키려면 이 맥락부터 이해를 잘 시켜야 하는데, 아무리 MCP들로 다 연결해둔다 해도 결국 다 아는 사람이 오케스트레이션 해주지 않으면 제대로 굴러가지 않는 것도 많이 체감했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람도 알아보기 힘들 정도로 기록들이 분류되어 있지 않으면 AI는 더 힘들 것이고, 설사 알아본다 해도 토큰량이 어마무지하게 들 것이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;따라서 체계화 된 기록 저장 구조(세컨드 브레인에서 말하는 정보 분류 등) + 이를 LLM에게 잘 넘겨줄 수 있는 환경(오케스트레이션, 하네스 엔지니어링 등)으로 컨텍스트 단편화를 해결하면 좋을 것이다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;LLM OS에서는?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://x.com/karpathy/status/1723140519554105733&quot;&gt;OpenAI의 안드레 카파시(Andrej Karpathy)가 &lt;b&gt;LLM OS&lt;/b&gt; 개념을 제안&lt;/a&gt;하며, LLM이 컴퓨터의 CPU 역할을 하고 컨텍스트 윈도우(Context Window)가 RAM 역할을 하게 될 것이라 말한 적이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 관점에서 보면 LLM을 단순 질의-답변에만 사용하기보다 &lt;b&gt;흩어진 맥락들을 잘 연결하며 하나의 거대한 지식 그물망(제텔카스텐 - Zettelkasten)으로 유지하는 것에서 더 큰 가치를 끌어낼 수 있지 않을까.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마치 과거의 OS가 메모리 단편화를 잘 해결하고 캐시 히트율을 높이는 방향으로 발전해온 것처럼, 앞으로의 LLM은, LLM OS로 거듭나려면 컨텍스트 단편화를 잘 해결하고 토큰 사용량을 줄이는 방향으로 발전할 수밖에 없지 않을까 싶다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;572&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blIqsk/dJMcagkDzIw/8P54CcGJzWwwLBz4DlC8ZK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blIqsk/dJMcagkDzIw/8P54CcGJzWwwLBz4DlC8ZK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blIqsk/dJMcagkDzIw/8P54CcGJzWwwLBz4DlC8ZK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblIqsk%2FdJMcagkDzIw%2F8P54CcGJzWwwLBz4DlC8ZK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;279&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;572&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;lt;참고자료들&amp;gt;&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arxiv.org/abs/2602.08382&quot;&gt;https://arxiv.org/abs/2602.08382&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://medium.com/@aaronxdsilva/the-complete-guide-to-rag-context-fragmentation-and-how-semantic-objects-solve-it-de9c8d3c21f4&quot;&gt;https://medium.com/@aaronxdsilva/the-complete-guide-to-rag-context-fragmentation-and-how-semantic-objects-solve-it-de9c8d3c21f4&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://arya.ai/blog/ai-context-fragmentation&quot;&gt;https://arya.ai/blog/ai-context-fragmentation&lt;/a&gt;&lt;/p&gt;</description>
      <category>사색과 잡념 사이</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/39</guid>
      <comments>https://turtle-hwan.tistory.com/entry/%EA%B8%B0%EB%A1%9D%EC%9D%98-%ED%8C%8C%ED%8E%B8%ED%99%94%EB%A5%BC-%EC%84%B8%EC%BB%A8%EB%93%9C-%EB%B8%8C%EB%A0%88%EC%9D%B8%EC%97%90-LLM%EC%9D%84-%EB%B6%99%EC%97%AC-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%EB%8B%A8%ED%8E%B8%ED%99%94%EC%99%80-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EB%8B%A8%ED%8E%B8%ED%99%94fragmentation#entry39comment</comments>
      <pubDate>Sun, 29 Mar 2026 23:58:56 +0900</pubDate>
    </item>
    <item>
      <title>우리, 프로그래머들 We, Programmers | 로버트 C. 마틴 서평</title>
      <link>https://turtle-hwan.tistory.com/entry/%EC%9A%B0%EB%A6%AC-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%93%A4-We-Programmers-%EB%A1%9C%EB%B2%84%ED%8A%B8-C-%EB%A7%88%ED%8B%B4-%EC%84%9C%ED%8F%89</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI의 시대 속에서 프로그래밍의 역사를 복기할 수 있는 책&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;길벗 출판사로부터 도서를 제공받았으며, 개인적인 의견을 바탕으로 작성했음을 미리 밝힙니다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;458&quot; data-origin-height=&quot;589&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SokqZ/dJMcaaj6THl/96ZVSkfhKShjHMoSGmI150/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SokqZ/dJMcaaj6THl/96ZVSkfhKShjHMoSGmI150/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SokqZ/dJMcaaj6THl/96ZVSkfhKShjHMoSGmI150/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSokqZ%2FdJMcaaj6THl%2F96ZVSkfhKShjHMoSGmI150%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;386&quot; data-origin-width=&quot;458&quot; data-origin-height=&quot;589&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 컴공 교수님이 하시던 이야기가 있었다. 컴퓨터공학은 다른 학문들에 비하면 생긴 지 얼마 안 된 아주아주 신생 학문이라고. 그럼에도 너무나 발전 속도가 빨라 우리 모두가 항상 뒤처지고 있다고.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ChatGPT부터 Claude, Gemini 등 LLM의 발전이 엄청 빨라졌고, 이를 많이 활용해서 개발 중인 나도 항상 시대와 기술에 뒤처지는 것은 아닌지 압박감이 크다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 책이 AI 시대의 프로그래밍에 대한 어떤 해답을 주는 것은 아니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼에도 책을 읽으면서 컴퓨터 공학, 프로그래밍의 역사를 돌이켜보니 이미 컴퓨터 공학은 엄청난 속도로 발전해왔고, 개발자들은 항상 위기감을 느끼고 있었구나를 깨달았다. 어셈블리어가 나왔을 때, 포트란, C언어가 나왔을 때, Java와 같은 객체지향 언어가 나왔을 때, 애자일과 XP, 소프트웨어 개발 방법론이 나왔을 때도 지금의 AI와 비슷한 패러다임의 전환기이자 마찬가지의 충격이 그 당시 엔지니어들을 덮치지 않았을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역사의 산증인이자 꾸준히 엔지니어로 활동한 거장의 생각과 느낀 점과 겪었던 일대기를 이렇게 정리된 글로 볼 수 있다는 점이 아주 좋았다.&amp;nbsp;&lt;a href=&quot;https://youtu.be/UBXXw2JSloo&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;궁금해서 찾아보니 The PrimeTime 유튜버와 저자 로버트 C. 마틴 (엉클 밥)의 인터뷰 영상도 볼 수 있었다.&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=UBXXw2JSloo&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/bgxIZq/dJMb8Z3oMUl/JTGOJku9yjYgwbi7JH8PW0/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=462_220_704_484,https://scrap.kakaocdn.net/dn/gFqln/dJMb8SpFtnr/5D26brUijxCH6cVM2lBQ8k/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=462_220_704_484&quot; data-video-width=&quot;300&quot; data-video-height=&quot;169&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;I Interviewed Uncle Bob&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/UBXXw2JSloo&quot; width=&quot;300&quot; height=&quot;169&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LISP 계열의 클로저(Clojure)에 대한 이야기와 구문적 제약이 거의 없는 Clojure에서도 클린 코드 원칙을 어떻게 지켜나갈 수 있는지에 대한 이야기를 한다. (유튜브 베스트 댓글이 &amp;ldquo;JAVA에 대한 배신&amp;rdquo;이다. ㅋㅋㅋ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 이분도 변화하는 기술에 열심히 적응하려 노력하는 한 명의 프로그래머이고 엔지니어라는 사실이 와닿았다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서도 이러한 AI 발전과 개발자 일자리에 대한 이야기가 종종 나오는데, 동료 개발자 분이 이런 얘기를 한 적이 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옛날엔 분명 기계어를 치는 것이 더 재밌는 사람도 있었을거고, 천공 카드를 뚫는 것에 재미를 느껴서 프로그래머가 된 사람도 있을 거라고. 그런데 이 사람들은 어셈블리어와 C언어가 나와서 재미를 잃어서 프로그래머를 관두거나 오히려 새로움에 적응해서 더 생산성이 올라갔을 수도 있지 않냐고.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;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;AI를 잘 쓰면 코드 생산량이 극도로 증가한다는 것은 부정할 수 없는 흐름이 되었고, 어셈블리어나 고수준 언어가 처음 나왔을 때만큼이나 변화의 시기에 서 있다고 느낀다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쩌면 이제 자연어 자체가 고수준 언어 이후의 하나의 프로그래밍 가능한 추상 레이어가 되어, 누구나 자연어로 원하는 고수준 언어의 코드를 생성하고, 컴파일러가 어셈블리어로 바꾸고.. 하는 과정으로 자연스레 변화할 것이라 느껴진다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에 나온 대로 앞으로 하나의 언어만 남는다면, 그건 (저자가 말한 LISP 보다는..ㅎㅎ) 결국 자연어가 될 것이라는 강한 예감을 받았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 자연어는 본질적으로 모호하며 이를 이해하는 LLM은 비결정적이고 확률적이라는 큰 차이가 있다. 아무리 LLM이 발전한다 해도 자연어의 모호한 특성 때문에 프롬프트 엔지니어링부터 자연어를 어떻게 논리적인 기술 명세로 바꾸고, 컴퓨터에서 결정적으로 실행할 수 있게 할 것인가에 대한 부분에서 엔지니어의 영역이 남아 있을 것이다. 이 엔지니어의 역할과 하는 일은 지금의 개발자와는 조금, 어쩌만 많이 다를 수도 있겠지만 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;소프트웨어 공학 교수님이 항상 말씀하시던 &amp;ldquo;모든 것을 한 방에 해결하는 은 탄환은 세상에 없다&amp;rdquo;, &amp;ldquo;모든 기술은 트레이드 오프다&amp;rdquo;라는 문구가 떠오른다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책의 서두에 &lt;b&gt;아직도 프로그래머가 없는 세상은 실현되지 않았고, 어떤 분야의 프로그래머를 고용해야할지 고민하는 수준에 이르렀다&lt;/b&gt;는 말이 기억에 남는다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;우리, 프로그래머들은 세상 디테일을 책임지는 사람들이다.&lt;/span&gt;&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI의 시대에서 0에서 0.9까지의 프로덕트를 만드는 것은 이전과 비교도 안되게 쉬워지고 빨라졌다. 그런데 0.9에서 1을 가는 그 사이 과정은 아직까지는 AI가 없을 때랑 크게 차이가 나지 않는 것 같다. AI로 인해 코드베이스가 아주 커지고 다루는 비즈니스 범위가 많아지면서 오히려 이 구간에서 병목에 걸리고 시간이 많이 들기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책에 나온 이 글귀처럼 0.1, 0.01에 집중하며 세상 디테일을 책임지는 사람들은 언제나 그랬듯이 계속 필요할 것이고, AI로 인해 코드가 더 많이 생산되게 된다면 더더욱 많이 필요해지지 않을까.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 기술적 격동기에 도달했고 그만큼 어렵지만 기회도 아주 많다고 느껴진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 강한 자가 살아남는게 아니라 버티고 살아남은 자가 강한 것 아닐까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/38</guid>
      <comments>https://turtle-hwan.tistory.com/entry/%EC%9A%B0%EB%A6%AC-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EB%93%A4-We-Programmers-%EB%A1%9C%EB%B2%84%ED%8A%B8-C-%EB%A7%88%ED%8B%B4-%EC%84%9C%ED%8F%89#entry38comment</comments>
      <pubDate>Tue, 3 Mar 2026 01:24:47 +0900</pubDate>
    </item>
    <item>
      <title>2025년에 했던 일들</title>
      <link>https://turtle-hwan.tistory.com/entry/2025%EB%85%84%EC%97%90-%ED%96%88%EB%8D%98-%EC%9D%BC%EB%93%A4</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;2025년 주요 활동 타임라인&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;사실 아래 항목 하나하나가 풀어서 쓰면 글 하나씩은 나올 만한 것들인데 시간 날 때 써봐야겠다.&amp;nbsp;&lt;br /&gt;안 써져 있으면 독촉 댓글 달아주시면 아마도.. 조금 더 빨라지지 않을까 싶네요 :)&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;요약&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2025에 했던 일들.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmPCbY/dJMcadgGxjM/Vg3QbC6YcuGfbkC78HI7UK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmPCbY/dJMcadgGxjM/Vg3QbC6YcuGfbkC78HI7UK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmPCbY/dJMcadgGxjM/Vg3QbC6YcuGfbkC78HI7UK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmPCbY%2FdJMcadgGxjM%2FVg3QbC6YcuGfbkC78HI7UK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2816&quot; height=&quot;1536&quot; data-filename=&quot;2025에 했던 일들.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현업 경험 : 2개월 간의 현장실습 + 8개월 간의 스타트업&lt;/li&gt;
&lt;li&gt;커뮤니티 : 3개의 IT 동아리 운영진 &amp;amp; 많은 면접..&lt;/li&gt;
&lt;li&gt;실사용자 사이드 프로젝트 성공&lt;/li&gt;
&lt;li&gt;IT 교육 봉사 / 기술 발표 / 핸즈온 세션 진행&lt;/li&gt;
&lt;li&gt;많은 부스 운영 경험..&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;겨울방학 (2024.12 ~ 2025.02)&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;프론트엔드 현장실습&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;600만 MAU에다 인지도도 높고 직접 써보기도 했던 사용자향 SaaS인 다이닝코드에서 일할 수 있게 되었다. 이전에 엘리스에서 FE 일경험이 있었긴 하지만, 본격적인 풀타임 회사 기여는 이곳이 처음이었고, 기대도 컸고 배움도 많았다.&lt;/li&gt;
&lt;li&gt;Vanilla JS부터 PHP, React까지 다양한 프로덕션 코드를 놓고 고민해볼 기회였다.&lt;/li&gt;
&lt;li&gt;AWS S3 Object Lambda + CloudFront까지 건드리면서 이미지 최적화와 비용 최적화 설계 및 적용을 해볼 수 있었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;KU Global Startup Frontier CES 2025 &amp;amp; 창업 교육 참가&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2025.01.05 ~ 2025.01.16 동안 라스베이거스에서 열린 CES와 로스엔젤레스의 PSU에서 창업 교육을 들었다.&lt;/li&gt;
&lt;li&gt;지원해주신 건국대 창업지원단과 희승선생님께 감사하고, 창업에 뜻이 있으면서도 각자의 분야에서 정말 열심히 살아가는 친구들을 많이 만날 수 있어 좋았다.&lt;/li&gt;
&lt;li&gt;CES에서도 역시나 AI 기술이 주된 화두였고, 그때 써둔 글을 보니 &quot;기술 우위가 옅어지고 AI로 개개인의 생산성이 극대화되고 있는 이 시점에 한 명 한 명의 사람이 더더욱 중요하다&quot;, &amp;ldquo;스타트업들은 기존 생태계의 부족한 점을 파고드는 반면, 대기업들은 영역을 확장하면서 생태계를 모두 자신의 제품들로 채우려는 차이점 발견&amp;rdquo; 라는 감상평을 남겼었다.&lt;/li&gt;
&lt;li&gt;제조 쪽에서 중국의 발전이 엄청나다고도 느꼈었다. LG 투명 디스플레이가 24&amp;rsquo; CES에 처음 나온 것으로 알고 있는데 1년 만에 퀄리티는 떨어지나 비슷하게라도 따라만든 것 등..&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;LinKU 크롬 확장 프로그램 개발 및 배포&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2025.02.25 첫 배포&lt;/li&gt;
&lt;li&gt;건국대 관련 다양한 링크 모음 크롬 확장이고, 내가 불편해서 만들고 싶었던 게 첫 시작이었다. &lt;a href=&quot;https://github.com/Turtle-Hwan/LinKU/commit/e89e9383d7bde936204aac419292e3129efcc03f&quot;&gt;심지어 첫 커밋은 24년 3월&lt;/a&gt;인데 미루고 미루다 AI의 발전에 힘입어 시작!&lt;/li&gt;
&lt;li&gt;배포 후 단 이틀만에 200+ 설치&lt;/li&gt;
&lt;li&gt;단순 링크 모음을 떠나 좀 더 실용적인 기능이 있으면 좋지 않을까 하다 생각난 것이 eCampus TODO를 연동해주는 것이었다. 맨날 이캠 들어가기 귀찮아서 과제 디데이 까먹기 일쑤였는데 이걸 편하게 만들고 싶었지만! 이를 위해 로그인 API 따오는 것이랑 CORS 해결도 필요했다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이외에도 GitHub을 이미지 서버 대용으로 쓰고, CI/CD 붙이는 작업 등을 했는데 이건 다른 글에서 풀어보겠다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;기타 활동&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MDN 번역 기여 머지 완&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1학기 (2025.03 ~ 2025.06)&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;에코업 3기 서포터즈&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 맡게 된 여러 뒷 이야기가 있는데.. 길어지니 다른 글에서 풀어야겠다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;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;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;VIC, CESM2 모델 세팅 및 발표&lt;/li&gt;
&lt;li&gt;브루트포싱 공격 감지 및 대응
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;fail2ban, 방화벽 설정, sudo 권한 설정&lt;/li&gt;
&lt;li&gt;sudo.log 기록 등 보안 조치 강화&lt;/li&gt;
&lt;/ul&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;KUIT 5기 부회장 &amp;amp; 웹 파트장&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4기 웹 파트장에 이어 5기 부회장을 맡았는데 21학점과 회사와 함께 하려니 이전 기수에 비해 부원들에게 많이 신경써주지 못했던 것 같아 미안한 마음이 컸다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;20명 가량 면접 후 부원 선발 / 5기 운영진 활동&lt;/li&gt;
&lt;li&gt;MT, 기획설명회, 데모데이, 웹 강의 등 다양한 활동&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Google Developer Groups on Campus Konkuk (&lt;b&gt;舊 GDSC)&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;사실상 이틀 해커톤이 되어 버린 Google Solution Challenge&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여행 + 단체 AI 채팅 컨셉으로 4인 팀&lt;/li&gt;
&lt;li&gt;다들 취준 + 학업으로 바쁜 사람들이라.. Next.js 기반 Chatting API, 지도 API, gemini API 연결을 하루 밤새면서 다 했었다. &lt;del&gt;솔루션 해커톤&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;5월 중순 쯤이었는데 AI의 강력함을 이때부터 체감했던 것 같다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;커뮤니티 활동 :&lt;/b&gt; Kprintf 행사 지원 (2025.05.24)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유명 현업 개발자 분들을 연사자로 모셔서 발표를 듣는 Kprintf를 개최하고, 운영진으로 주관했다.&lt;/li&gt;
&lt;li&gt;오히려 이리저리 뛰어다니느라 연사자 분들과 대화를 많이 못 한 것 같아 아쉬웠다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;봉사 활동 : 경동초 코딩 교육 봉사&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 좋은 경험이어서 따로 하나 글을 써봐야겠다 !!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스크래치, HTML/CSS/JS + Gemini AI 코딩 교육 봉사 / 05.21, 05.28, 06.04 진행&lt;/li&gt;
&lt;li&gt;초등학생들의 빠른 학습 능력에 놀랐다. HTML 간단하게 알려주고 Gemini로 웹 게임 만들게 시켰는데 엄청난 상상력으로 진짜 다양한 것들을 만들어냈었다.&lt;/li&gt;
&lt;li&gt;심지어 그 전날 2시간 정도만에 React + supabase 바이브로 코드 자랑 게시판을 직접 만들어가서 각자 코드를 올리게 하고 발표까지 시켜보았던 재밌는 시간이었다.&lt;/li&gt;
&lt;li&gt;담임 선생님께 어디서도 경험하기 힘든 좋은 수업이었다고 손편지와 쿠키까지 받았다.. 그 편지는 지금 동방에 잘 전시되어 있으려나.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;AI 스타트업 입사 및 근무 (25.04 ~ 25.12)&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LinKU를 만든 덕에 주위에서 희귀한 크롬 확장 개발자로 불리우게 되었고(?) 그 덕에 친구의 소개를 받아 간략한 면접을 보고 입사하게 되었다.&lt;br /&gt;21학점을 듣고 있었기에 초기에는 외주 개발과 시간제 근무의 그 어디 중간쯤의 형태로 시작했다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LLM Safety 제품을 만들어가는 완전 초기에 합류했었고, 처음에는 크롬 확장으로 시작했었다. 그러나 브라우저 확장의 특성 상 브라우저 밖에서 일어나는 통신을 잡을 수 없다는 한계가 있어 데스크톱 앱으로 피봇팅하게 되었다.&lt;/li&gt;
&lt;li&gt;Python으로 AI 서버 통신 + 데스크톱 앱 + 로컬 프록시 + 위험 감지 시 notification이 되는 PoC 코드를 이틀 정도에 만들었던 것 같다. 이후 이 방향으로 계속 개발해나갔고, Python 코드를 주로 보게 되었다.&lt;/li&gt;
&lt;li&gt;FE를 넘어서 FastAPI 서버, AI Serving, Infra, MCP 개발 등 AI 관련된 더 다양한 코드를 보고 프로덕션에 내는 경험을 했다.&lt;/li&gt;
&lt;li&gt;회사임에도 그 안에서 정말 활발한 연구 활동을 하고 탑티어 논문도 많이 내고 계셨고, 0에서 1을 어떻게 만들어내는지, 초기에 매출을 어떻게 내는지 등 초기 스타트업에서 많이 배울 수 있었다.&lt;/li&gt;
&lt;li&gt;코엑스에서 전시 부스도 여러 번 운영해보게 되었고, 여러 유명 회사의 AI 관계자 분들도 볼 수 있었다.&lt;/li&gt;
&lt;li&gt;방학엔 풀타임으로, 2학기에는 주3일로 근무를 이어나가게 되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;여름방학, 2학기 (2025.07 ~ 2025.12)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;방학 때는 풀타임 회사를 다니느라 정신이 없었다. 생각해보니 학생개발팀도 있었네..&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;학생개발팀 활동 (25.06 ~ 25.08)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;학교 정보운영팀에서 차세대학사정보시스템 개선 관련된 개발 관련 학생을 뽑길래 덥석 신청해버렸고, 뽑혀버렸다. 아무래도 LinKU 만들었던 게 인상적이었던 것 같다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;알고 보니 학사 시스템에 직접 기여하는 것은 아니었고, 기존 학정시의 UI, UX 적인 불편함을 뽑아서 몇 가지 개선 방향 제시와 학생들의 의견을 듣고 싶어하신 것 같다.&lt;/li&gt;
&lt;li&gt;회사와 병행하느라 많은 시간을 투자하지 못해 아쉬웠다. 흔치 않은 학교 공식 도메인을 받아 서버를 띄우는 기회인데 말이다. 그런데 학교 뉴스와 홈페이지까지 얼굴이 실려버렸다..&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;GDGoC Core 멤버 활동&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;면접 진행 (10명, 2025.09.10~12)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;교내의 Google Developer Groups 25-26 세션의 운영진(Core)를 맡게 되었고&amp;hellip; 또 면접을 보게 되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;MCP 관련 테크톡 발표&lt;/b&gt; : &quot;Agentic AI란 무엇일까 : MCP 개발자가 들려주는 Agent 이야기&quot;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MCP를 개발해 본 경험을 바탕으로 GDG에서 테크톡 세션을 맡아 20분 정도 발표했었고, 유튜브에도 올리게 되었다. &lt;del&gt;그리고 이걸 링크드인에서 보신 대표님&lt;/del&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;DevFest 핸즈온 세션 진행&lt;/b&gt; : GDG on Campus 연합에서 진행하는 AI, Agent 관련 핸즈온 세션에 운영진 중 몇 명과 함께 참가해서 Gemini에 MCP 여러 개 붙여서 간단한 코딩 해보는 핸즈온을 진행했다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JS Deep Dive 스터디 / 대규모 시스템 설계 스터디 / AWS SAA 스터디 / &lt;del&gt;유기해버린 스터디들&lt;/del&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;del&gt;왜 이렇게 스터디를 많이 했지.. 그리고 아직도 끝나지 않는 스터디들&lt;/del&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;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;교내 중앙동아리 메이커스팜 운영진 (25.03 ~ 26.??)&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KU 글스프에서 만난 친구가 마침 멋쟁이 사자처럼 운영진을 하다 왔었고, 교내에 IT 중동을 시작하려 하는 참이었다. 특히 또 외주, 개발 수익화, AI 관련 키워드에 관심이 많았기에 자연스럽게 합류하게 되었다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;20명 가량 면접 진행 / 여러 부스, 행사&lt;/li&gt;
&lt;li&gt;MCP, Agent 관련 여러 행사 주최
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MCP라는 개념이 처음 나왔을 때 동아리 방에 모여 Perplexity, Notion, Figma MCP 등등 서로 도와가며 연결해보고 써보는 세션도 하고, Figma AI도 써보고, Claude Code 후기도 공유했었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Agent, 바이브 코딩과 같은 키워드에 관심 있고 특히 얼리어답터로 빠르게 기술을 적용하고 써보는 사람들을 만나기 쉽지 않은데 이 동아리를 통해 AI Agent 얼리어답터 친구들을 많이 만나고 또 서로 공유하는 장이 될 수 있어 좋았다.
&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;오픈소스 기여모임 컨퍼런스 참여&lt;/b&gt;&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;김인제님이 하시는 오픈소스 기여 모임에 아는 사람들이 여럿 있어 컨퍼런스에 가서 강연을 들을 기회가 생겼다. 아직 오픈소스에는 docs 기여뿐인데, 코드 기여도 언젠가는 하고 싶다.&lt;/p&gt;
&lt;/blockquote&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;AI에게 판단을 맡기지 말고, 개발자가 구조화하고 아키텍처를 짜는 경험의 중요성&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;2026년에는 선택과 집중, 그리고 정리에 중점을 두어야겠다&lt;/span&gt;&lt;/blockquote&gt;</description>
      <category>사색과 잡념 사이</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/37</guid>
      <comments>https://turtle-hwan.tistory.com/entry/2025%EB%85%84%EC%97%90-%ED%96%88%EB%8D%98-%EC%9D%BC%EB%93%A4#entry37comment</comments>
      <pubDate>Wed, 18 Feb 2026 19:16:44 +0900</pubDate>
    </item>
    <item>
      <title>2025년 회고</title>
      <link>https://turtle-hwan.tistory.com/entry/2025%EB%85%84-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;2025 회고.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cE6jYG/dJMcagxHb8m/PKpCK8xUMoBDzT1BRpduck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cE6jYG/dJMcagxHb8m/PKpCK8xUMoBDzT1BRpduck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cE6jYG/dJMcagxHb8m/PKpCK8xUMoBDzT1BRpduck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcE6jYG%2FdJMcagxHb8m%2FPKpCK8xUMoBDzT1BRpduck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2816&quot; height=&quot;1536&quot; data-filename=&quot;2025 회고.png&quot; data-origin-width=&quot;2816&quot; data-origin-height=&quot;1536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;학교와 주변에서 모인 개발자 친구들과 블로그 안쓰면 죽는 모임이라는 벌금형 모임을 하는 중인데, 12주간 안 써서 무려 6만원짜리 회고 글이 탄생해버렸다.&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;노션 AI가 생각보다 성능이 많이 좋아진 것 같다. 이전에 기록해둔 것이 많아 그럴 수도 있겠으나 어느 정도 중요 내용은 다 뽑아주어 정리가 편했다. 특히나 여러 일을 하고 사건을 겪으며 느낀 것들을 정리했음에도 기억 저편에 숨겨져 있던 기록들을 다시 보니 감회가 새롭다. AI와 함께한 1년이라는 생각도 든다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2025년, 무엇을 하려 했는가&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;IT 커뮤니티 활동, 학생과 현업의 경계 돌파하기&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2024년에 KUIT과 GDSC라는 교내의 굵직한 개발 동아리 활동을 하며 다양한 사람을 만나고, 개발 실력적으로도 개발 외적으로도 정말 뛰어난 사람들을 많이 만났었다. 이러면서 4학년이 되어버렸고 자연스레 &amp;ldquo;이렇게 개발자로서 뛰어난 사람이 되고 싶다&amp;rdquo;, &amp;ldquo;과연 내 실력이 어느 정도일까?&amp;rdquo;, &amp;ldquo;취업은 가능할까?&amp;rdquo;, &amp;ldquo;실무를 해보고 싶다&amp;rdquo; 와 같은 생각들이 머리 속에 맴돌았었다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;나중에 2024년 회고 링크도 넣기 (안 넣어져 있다면 독촉 댓글 달아주세요..)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;2025년의 목표는 다음 세 가지였다.
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;개발 활동 많이 하기&lt;/li&gt;
&lt;li&gt;어려운 시장 속에서 취업할 정도의 실력 쌓기&lt;/li&gt;
&lt;li&gt;그러면서도 졸업 요건 모두 채우기&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2025년, 어떻게 성장했는가&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;돌이켜 봤을 때, 결과적으로는 위 세 가지 목표를 만족할만큼 달성했다고 느껴진다.&lt;/blockquote&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&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;LinKU라는 크롬 확장 프로그램을 만들어서 실사용자 200+명을 달성해봤고, 주위에서 잘 쓰고 있다는 얘기도 아주 많이 들어 오픈소스와 사용자향 SaaS 만드는 재미를 제대로 느꼈고 행복했다.&lt;/li&gt;
&lt;li&gt;학생개발팀이라는 학교 정보운영처 하위의 공식 팀에 소속되어 UX 개선 프로젝트를 진행했고, 학교 뉴스에도 실려보게 되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;어려운 시장 속에서 취업할 정도의 실력 쌓기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;운 좋게 실무를 경험할 수 있는 좋은 회사에서 현장 실습을 한 것을 시작으로, 동아리에서 만난 친구의 소개와 크롬 확장 프로그램 제작 경험 덕에 폭발적으로 성장하는 초기 스타트업에 합류하게 되었다.&lt;/li&gt;
&lt;li&gt;초기 스타트업답게 원래 주 기술 스택이던 프론트 뿐 아니라 피봇팅하며 Python Backend, AI Serving, Infra, Cloud 등 다양한 기술을 프로덕트 단에서 접해볼 수 있었다.&lt;/li&gt;
&lt;li&gt;네카라쿠배당토 중 두 군데의 인턴에 합격했었다. 냉정하게 아직 정규직을 바로 합격할 실력은 안 되더라도, 인턴 합격선 정도의 실력을 인정받은 것 같아 기뻤다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;졸업 요건 모두 채우기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공대 복수전공&amp;hellip; 이라는 스스로 불러온 재앙에 짓눌렸으나 7학기 동안 힘들게 150학점을 듣고, 막학기는 다행히도 10학점만 들으면서 상대적으로 널널하게 졸업 요건을 모두 채울 수 있었다.&lt;/li&gt;
&lt;li&gt;항상 21학점만 듣다가 막학기 10학점 들으니깐 아주 살 거 같았다. 그러나 그새 여유를 못 참고 회사와 병행을 한다는 선택을 해버렸지만 말이다..&lt;/li&gt;
&lt;li&gt;학생 신분과 회사를 병행하면서 다행히도 졸업 요건은 다 맞추어 졸업 가능해졌다!!!!!!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2026년, 무엇을 할 것인가&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;쌓아온 경험은 차고 넘치게 많지만, 정리가 안 되어 있다는 이야기를 나 자신도 느끼고 주변으로부터도 듣고 있다. 휘발되지 않게 정리하는 한 해가 되길.&lt;/li&gt;
&lt;li&gt;그리고 정규직으로 취업 하고 싶다.&lt;/li&gt;
&lt;li&gt;학교와 일을 병행하면서 더 그렇게 되었을런지는 모르겠으나, 일과 삶의 밸런스가 깨지고 집까지 일을 들고온다는 느낌과, 중심을 잡지 못하고 우선순위를 못 세우며 들어오는 대로 일을 처리하고 있다는 느낌을 받는다. 단기적인 성과는 높아지겠으나 장기적으로는 매우 좋지 않음을 깨달았기에 좀 더 체계적이고 우선순위를 세워 일하는 방법을 체화하고 싶다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2025년 주요 활동 타임라인&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://turtle-hwan.tistory.com/entry/2025%EB%85%84%EC%97%90-%ED%96%88%EB%8D%98-%EC%9D%BC%EB%93%A4&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://turtle-hwan.tistory.com/entry/2025%EB%85%84%EC%97%90-%ED%96%88%EB%8D%98-%EC%9D%BC%EB%93%A4&lt;/a&gt;&lt;/p&gt;</description>
      <category>사색과 잡념 사이</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/36</guid>
      <comments>https://turtle-hwan.tistory.com/entry/2025%EB%85%84-%ED%9A%8C%EA%B3%A0#entry36comment</comments>
      <pubDate>Mon, 2 Feb 2026 00:04:16 +0900</pubDate>
    </item>
    <item>
      <title>GDGoC Konkuk 테크톡 발표 후기 - MCP, AI Agent란 무엇일까</title>
      <link>https://turtle-hwan.tistory.com/entry/GDGoC-Konkuk-%ED%85%8C%ED%81%AC%ED%86%A1-%EB%B0%9C%ED%91%9C-%ED%9B%84%EA%B8%B0-MCP-AI-Agent%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;GDGoC Konkuk 테크톡 발표 후기.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rjdKw/dJMcadmL8z8/5MMvER38kBdpDh7YkL22Z1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rjdKw/dJMcadmL8z8/5MMvER38kBdpDh7YkL22Z1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rjdKw/dJMcadmL8z8/5MMvER38kBdpDh7YkL22Z1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrjdKw%2FdJMcadmL8z8%2F5MMvER38kBdpDh7YkL22Z1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;375&quot; data-filename=&quot;GDGoC Konkuk 테크톡 발표 후기.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&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;학교에서 GDGoC, Google Developer Group on Campus Konkuk 에서 25-26 Core 운영진으로 활동하고 있다. 세션을 기획하던 도중 테크톡을 진행할 수 있냐는 좋은 제안을 받아 MCP와 Agent AI를 주제로 테크톡을 진행하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사에서 기회가 닿아 MCP를 개발해보기도 했고, 공모전을 위해 MCP를 만들어보기도 했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 MCP가 나오자마자 열심히 이것저것 시도하면서 사용해봤던 유저로서 발표 정도야 금방 준비해서 하겠지라고 생각했었는데, 이는 오판이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지난 글을 작성하면서도 느꼈던 것인데 Agentic AI와 AI Agent도 제대로 구분하지 못하고 있었고, MCP에 대해서도 겉핥기식으로만 만들어봤지 좀 더 깊게 어떤 방식으로 구성되는지는 잘 몰랐는데 이번 기회에 많이 알아볼 수 있었다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;요즘 일이 많기도 하고, 눈 앞에 닥친 일들 해결하기도 버거워서 &amp;ldquo;빠른&amp;rdquo; 문제 해결에만 치중하고 있었던 것은 아닌가 반성하게 되었다. 앞으론 원래 하던 대로 빠른 &amp;ldquo;문제 해결&amp;rdquo;에 방점을 찍고 깊게 깊게 알아가야겠다.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진행했던 내용을 단락별로 간략히 요약해 작성해보았으며, Youtube에 발표 영상도 올라가는 경험도 할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://youtu.be/VGkkZX8T4m4?si=IF_GPayHYzMZxflp&quot;&gt;https://youtu.be/VGkkZX8T4m4?si=IF_GPayHYzMZxflp&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;video&quot; data-ke-style=&quot;alignCenter&quot; data-video-host=&quot;youtube&quot; data-video-url=&quot;https://www.youtube.com/watch?v=VGkkZX8T4m4&quot; data-video-thumbnail=&quot;https://scrap.kakaocdn.net/dn/byLgRV/hyZNbsGfVZ/Rwm9yFGjnhMhrdUBIk0buk/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720,https://scrap.kakaocdn.net/dn/OSt6i/hyZNdjJmAz/WwXsbmQaNCyRiauAa0bK7k/img.jpg?width=1280&amp;amp;height=720&amp;amp;face=0_0_1280_720&quot; data-video-width=&quot;860&quot; data-video-height=&quot;484&quot; data-video-origin-width=&quot;860&quot; data-video-origin-height=&quot;484&quot; data-ke-mobilestyle=&quot;widthContent&quot; data-video-title=&quot;Agentic AI란 무엇일까? MCP 개발자가 들려주는 Agent 이야기 [김지환]&quot; data-original-url=&quot;&quot;&gt;&lt;iframe src=&quot;https://www.youtube.com/embed/VGkkZX8T4m4&quot; width=&quot;860&quot; height=&quot;484&quot; frameborder=&quot;&quot; allowfullscreen=&quot;true&quot;&gt;&lt;/iframe&gt;
&lt;figcaption style=&quot;display: none;&quot;&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;말 잘하는 AI에서 일 잘하는 AI로&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기에는 챗봇이나 GPT, Gemini 같은 LLM이 발전해오며 어떻게 사람같이 대화를 하는가에 좀 더 초점이 맞추어져 있었다. 그런데 어느 순간 추론 능력을 평가하기 시작하더니 AI의 문제 해결 능력, 즉 일 잘하는 AI를 여러 기업에서 만들어나가고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 흐름 속에 Perplexity, 뤼튼, 릴리스AI와 같은 AI를 통해 사용자들이 직면한 문제를 해결해주겠다는 AI SaaS들이 엄청 많이 등장했다. 마찬가지로 Agent, AI Agent, Agentic AI 라는 용어들까지 등장했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;용어 정의가 생각보다 다양했는데, 참고한 레퍼런스는 다음과 같다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://cloud.google.com/discover/what-are-ai-agents?hl=ko&quot;&gt;Google Cloud&lt;/a&gt;에서는 Bot &amp;rarr; AI Assistant &amp;rarr; AI Agent로 설명하고 있다.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.samsungsds.com/kr/insights/agentic-ai-the-autonomous-era-of-artificial-intelligence.html&quot;&gt;Samsung SDS&lt;/a&gt;, &lt;a href=&quot;https://www.ibm.com/think/topics/agentic-ai&quot;&gt;IBM&lt;/a&gt;, &lt;a href=&quot;https://www.lgcns.com/kr/service/ai/agentic-ai&quot;&gt;LG CNS&lt;/a&gt;의 자료에서는 더 고도화되어 목표도 스스로 정하며 작업을 수행하는 단계를 Agentic AI라 칭하고 있다.&lt;/li&gt;
&lt;li&gt;Gen AI / Chat bot &amp;rarr; AI Agent &amp;rarr; Agentic AI 의 단계로 설명한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;단순한 자연어 대답을 넘어, LLM이 직접 task도 수행하게 하자는 것이다&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;AI의 진화 : 단순 Chatbot에서 Agentic AI 까지&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 각 단계는 어떻게 다른가?&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Chatbot, GenAI는 Input &amp;rarr; Model &amp;rarr; Output 단계만 존재하며, 우리의 대화형 입력에 따른 답변을 내놓는다.&lt;/li&gt;
&lt;li&gt;AI Agent는 Goal &amp;rarr; Agent &amp;rarr; Tools &amp;rarr; Output 단계로 수행하며, 사용자가 준 목표에 따라 다양한 도구(Tools)를 호출하여 작업을 진행한다.&lt;/li&gt;
&lt;li&gt;Agentic AI는 Objective &amp;rarr; Sub-Agents &amp;rarr; Tools + Memory &amp;rarr; Output 단계로 늘어나며, 주어진 목표(Objective)를 달성하기 위해, Sub Agent들을 두고 자율적으로 세부 목표를 정해 작업을 수행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Agentic AI가 주목받는 이유는 바로 이 자율성이다. &lt;b&gt;스스로 판단하고 행동하며, 피드백을 받아 반복 수행&lt;/b&gt;까지 가능해진다는 점이 큰 장점이라 느껴진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 이 과정에서 두 가지 큰 질문이 생겨난다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;AI Safety를 어떻게 보장할 것인가&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;수많은 Tool들을 어떻게 AI가 사용하게 할 것인가&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;AI가 외부 Tool과 연결되는 규칙, Model Context Protocol&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 Tool들을 AI가 편하게 사용하게 하기 위해 만들어진 MCP 이야기 위주로 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MCP는 용어가 어려워 보이지만 결국 하나의 서버이며, LLM과 외부 도구를 연결하기 위한 통신 규약, protocol 이라 생각하면 더 쉽게 다가갈 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1117&quot; data-origin-height=&quot;556&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b1qF4O/dJMcadtxItf/T33s61lber7kAVIHqwLxck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b1qF4O/dJMcadtxItf/T33s61lber7kAVIHqwLxck/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b1qF4O/dJMcadtxItf/T33s61lber7kAVIHqwLxck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb1qF4O%2FdJMcadtxItf%2FT33s61lber7kAVIHqwLxck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1117&quot; height=&quot;556&quot; data-origin-width=&quot;1117&quot; data-origin-height=&quot;556&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적인 작동 과정은 다음과 같다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;사용자가 자연어로 LLM에 명령을 내린다.&lt;/li&gt;
&lt;li&gt;LLM에서 사용자 명령을 해석해 적절한 MCP를 선택하고, 그 중 적절한 툴을 호출한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;LLM을 포함하고 MCP를 지원하는 서비스(VSCode, Cursor, Claude Desktop 등)가 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;MCP Server가 Tool에 명시된 동작을 한다. 이는 단순히 프롬프트 추가도, 노션이나 슬랙 같은 외부 도구 연결도 가능하다.&lt;/li&gt;
&lt;li&gt;LLM이 MCP로부터 받은 응답을 다시 파싱하여 해석하고 답변을 사용자에게 출력한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;결국 MCP도 하나의 서버 프로세스다&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자료를 조사하고 발표를 준비하며 깨달은 것은 결국 MCP도 하나의 서버 프로세스에 불과하다는 사실이다. 이렇게 서버라고 생각하고 보면 더 쉽다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;먼저 사용자와 LLM 서버 간에는 WebSocket, SSE, gRPC 등과 같이 기존 웹 채팅 서버 등에서 쓰이던 것과 동일한 통신 방법들을 사용한다.&lt;/li&gt;
&lt;li&gt;이후 LLM Client와 MCP 서버도 흔히 우리가 알고 있는 HTTP POST, WebSocket, SSE, stdio로 통신 가능하다. 특히 이 어떤 type으로 통신할지가 mcp.json type 부분에 명시하는 것이었다!!!
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;한 가지 특이한 점은 stdio 였는데, C언어 배울 때 나오던 그 stdio 맞다.. Standard Input / Output의 약자이며, 로컬에서 MCP 서버를 돌릴 경우 자식 프로세스로 띄우고 콘솔 IO를 바로 받아 이용한다 해서 신기했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;그럼 결국 MCP도 서버 프로세스가 띄워지는 것이므로, 외부 도구들과 연동할 때는 해당 도구들에서 제공하는 RESTful한 API를 HTTP로 끌어다 쓰면 그만인 것이었다!&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;1097&quot; data-origin-height=&quot;602&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bMfcIK/dJMcadAjkfB/YKRf9vWIuIHoUgytqlQ6kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bMfcIK/dJMcadAjkfB/YKRf9vWIuIHoUgytqlQ6kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bMfcIK/dJMcadAjkfB/YKRf9vWIuIHoUgytqlQ6kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbMfcIK%2FdJMcadAjkfB%2FYKRf9vWIuIHoUgytqlQ6kk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1097&quot; height=&quot;602&quot; data-origin-width=&quot;1097&quot; data-origin-height=&quot;602&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;MCP Server의 세 가지 구성요소&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Tools : LLM이 호출 가능한 도구들이다. 함수라고 생각하면 편하며, 이 안에서 fetch()등으로 원하는 API를 호출하고 응답을 파싱하면 된다.&lt;/li&gt;
&lt;li&gt;Resources : LLM이 먼저 참고할 수 있게 넣어두는 자료들이라 보면 된다. 주로 markdown을 넣으면 잘 읽어주는 것 같다.&lt;/li&gt;
&lt;li&gt;Prompts : LLM이 Tool과 Resource를 어떻게 사용할지 정해놓는 템플릿이다.&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;1077&quot; data-origin-height=&quot;550&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wtf7g/dJMcab3y3l4/beYPDPiZHy0imUTON0zKBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wtf7g/dJMcab3y3l4/beYPDPiZHy0imUTON0zKBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wtf7g/dJMcab3y3l4/beYPDPiZHy0imUTON0zKBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwtf7g%2FdJMcab3y3l4%2FbeYPDPiZHy0imUTON0zKBk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1077&quot; height=&quot;550&quot; data-origin-width=&quot;1077&quot; data-origin-height=&quot;550&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;VSCode에서 MCP 연결 방법&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;VSCode 기준으로 전역 MCP 설정 및 연결 방법, API token 같은 경우 어떻게 입력 변수로 빼낼 수 있는지를 설명해주었다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 MCP 부분도 빠르게 빠르게 추가되고, 사용자가 더 편하게 VSCode를 정말 빨리 업데이트 해주는 것 같다. 오픈소스로 공개되어 있던데 시간 나면 한 번쯤 기여해보고 싶다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;473&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0bDZd/dJMcagDNSLC/hRuKSpWWJpf4RGBEKgYVbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0bDZd/dJMcagDNSLC/hRuKSpWWJpf4RGBEKgYVbK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0bDZd/dJMcagDNSLC/hRuKSpWWJpf4RGBEKgYVbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0bDZd%2FdJMcagDNSLC%2FhRuKSpWWJpf4RGBEKgYVbK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;502&quot; height=&quot;473&quot; data-origin-width=&quot;502&quot; data-origin-height=&quot;473&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 설정 파일 사진을 보면 위에서 나왔던 것과 같이 type 부분에 MCP 서버와의 다양한 통신 방법을 명시해둔 것을 볼 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; 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;MCP도 뜯어보니 우리가 열심히 공부하던 CS 지식들로 모두 설명이 가능했고, 이런 지식들만 알고 구조만 파악하면 세부 코드는 AI의 도움을 받을 수도 있으니, MCP나 여러 서비스들을 금방 만들어낼 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;40~50명이 듣는 발표는 생각보다 더 떨렸고 준비에 더 많은 시간을 쏟아야 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 요소요소를 나열하면서 발표했던 수업이나 프로젝트 때와는 다르게 하나의 기술적 주제를 소개하고 이해시키려는 방향으로 짜다 보니 새로운 발표 경험이었다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;준비하면서 얻은 것들이 아주 많고 성취감을 많이 느껴서 기회가 되면 다양한 주제로 발표를 여럿 해보고 싶다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>대외활동/강연, 세미나</category>
      <category>agentic ai</category>
      <category>ai agent</category>
      <category>GDGoC</category>
      <category>Google Developer Group on Campus Konkuk</category>
      <category>Konkuk</category>
      <category>mcp</category>
      <category>model context protocol</category>
      <category>테크톡</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/35</guid>
      <comments>https://turtle-hwan.tistory.com/entry/GDGoC-Konkuk-%ED%85%8C%ED%81%AC%ED%86%A1-%EB%B0%9C%ED%91%9C-%ED%9B%84%EA%B8%B0-MCP-AI-Agent%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C#entry35comment</comments>
      <pubDate>Mon, 3 Nov 2025 01:20:27 +0900</pubDate>
    </item>
    <item>
      <title>Agentic AI 후기 3편 : 실험적으로 알아낸 Claude Code 활용 극대화 전략 5가지</title>
      <link>https://turtle-hwan.tistory.com/entry/Agentic-AI-%ED%9B%84%EA%B8%B0-3%ED%8E%B8-%EC%8B%A4%ED%97%98%EC%A0%81%EC%9C%BC%EB%A1%9C-%EC%95%8C%EC%95%84%EB%82%B8-Claude-Code-%ED%99%9C%EC%9A%A9-%EA%B7%B9%EB%8C%80%ED%99%94-%EC%A0%84%EB%9E%B5-5%EA%B0%80%EC%A7%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이전 편 :&amp;nbsp;&lt;a href=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-2%ED%8E%B8-Claude-Code-%ED%95%9C-%EB%8B%AC-%EC%82%AC%EC%9A%A9-%ED%8C%A8%ED%84%B4-%EB%B6%84%EC%84%9D&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.09.21 - [프로그래밍] - Agentic AI 후기 2편 : Claude Code 한 달 사용 패턴 분석&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;claude_code_usage3.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qnpWp/dJMb9jtSclP/kIAn2jkmqd8PjXHI23BUzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qnpWp/dJMb9jtSclP/kIAn2jkmqd8PjXHI23BUzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qnpWp/dJMb9jtSclP/kIAn2jkmqd8PjXHI23BUzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqnpWp%2FdJMb9jtSclP%2FkIAn2jkmqd8PjXHI23BUzK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;375&quot; data-filename=&quot;claude_code_usage3.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code 활용 극대화하기&lt;/span&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude Code를 사용하며 개발자가 직접 할 때보다 Agent를 시킬 때 더 효과가 좋았던 사례를 소개하려 한다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대표적으로 &lt;b&gt;단순 반복 작업 자동화나 문서화, 여러 대안 비교하며 최적 구현 방안 구체화 시키기에 주로 사용&lt;/b&gt;하니 효율이 올라갔다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이를 5가지로 정리해보았다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;에러 해결 반복 자동화&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;코드 수정에 대한 컨텍스트 유지시키기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;요구사항 구체화 시키기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;거대한 코드베이스에서 필요한 수정 부분 찾아내기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;테스트 케이스 빠르게 만들어내기&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;또한 이번에 찾아보니 공식 문서에서 프롬프트 엔지니어링 관련 좋은 정보들을 얻을 수 있어, Claude에서도 프롬프트 엔지니어링에 대한 많은 연구가 이루어지고 있다고 느꼈다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://docs.claude.com/ko/docs/build-with-claude/prompt-engineering/overview&quot;&gt;https://docs.claude.com/ko/docs/build-with-claude/prompt-engineering/overview&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1760962107851&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;프롬프트 엔지니어링 개요 - Claude Docs&quot; data-og-description=&quot;Responses are generated using AI and may contain mistakes.&quot; data-og-host=&quot;docs.claude.com&quot; data-og-source-url=&quot;https://docs.claude.com/ko/docs/build-with-claude/prompt-engineering/overview&quot; data-og-url=&quot;https://docs.claude.com/ko/docs/build-with-claude/prompt-engineering/overview&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/DYXEI/hyZLZzGB5p/Pfh1FTuxxs7TMaswhWBgh1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bQCP4r/hyZL3PAYHG/Y9czbZfkeJYIGJ3Hn812k1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://docs.claude.com/ko/docs/build-with-claude/prompt-engineering/overview&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.claude.com/ko/docs/build-with-claude/prompt-engineering/overview&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/DYXEI/hyZLZzGB5p/Pfh1FTuxxs7TMaswhWBgh1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/bQCP4r/hyZL3PAYHG/Y9czbZfkeJYIGJ3Hn812k1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프롬프트 엔지니어링 개요 - Claude Docs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Responses are generated using AI and may contain mistakes.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.claude.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 에러 해결 반복 자동화&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;코드 실행 / 빌드 &amp;rarr; 테스트 &amp;rarr; 코드 수정 &amp;rarr; 실행 &amp;rarr; 테스트 사이클을 자동으로 돌리게 하는 것&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 develop 환경에서는 문제가 없다가 build 환경이나 docker로 올릴 때만 터지는 오류가 몇 개 있었는데, build 시간이 오래 걸리는 경우 개발자가 직접 계속 빌드해보면서 확인하기가 아주 귀찮고 힘들다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이런 경우, 아래 구조의 프롬프트를 이용해서 오류가 없어질 때까지 claude code에서 자동으로 코드 수정 &amp;rarr; build test를 반복하게 하니까 아주 편했다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문제는 이런 과정을 반복할 때, 수정할 때마다 어디 오류를 수정했는지 컨텍스트가 기록되지 않는 블랙박스여서 나중에 확인할 때 너무 코드 범위가 많고 사람이 놓치기 쉽다는 것이다. 그래서 맨 아래 문장을 추가해 단계 별 변경점을 추적할 수 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;OOO 명령어로 빌드 가능해. OOO 코드로 테스트 가능해. 빌드 시에 OOO 오류가 발생하는 상태인데, 이를 먼저 해결하는 코드를 짜고, 실제로 빌드를 실행한 후에 테스트를 돌려줘. 이를 오류 없이 정상적으로 빌드가 될 때까지 계속 반복해줘.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단, 코드를 수정하고 빌드할 때마다 OOO.md에 어떤 방향으로 코드를 수정했고, 오류의 원인이 뭐였는지 기록해야 해.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특히 웹 개발일 경우, pnpm build하고, 오류 확인하고, 수정하고, 다시 build하고 확인하는 사이클 돌리기도 좋고, docker compose로 빌드하고, 배포하고, 테스트하고, 오류 확인 후 해결까지를 자동화시키기 좋다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다만 docker compose의 경우 자꾸 최신 명령인 docker compose ~ 가 아니라, 별도 패키지가 필요한 docker-compose ~ 명령을 사용하는 경우가 잦아 claude.md에 전역으로 추가해주었다. 또한 docker compose 파일도 처음 명령 시 명시적으로 지정하는 것이 훨씬 편했다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;## Docker Notes
- docker-compose 대신 docker compose 명령어를 사용할 것.
&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 코드 수정에 대한 컨텍스트 유지시키기&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #000000;&quot;&gt;사람이 준 task에 대한 코드 수정 이유와 컨텍스트가 기록되지 않아 불편한 점이 많아, &lt;br /&gt;이를 전역 Claude.md에 집어넣었다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Claude.md에 아래 프롬프트를 입력해두었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이를 통해 매일매일 내가 한 일을 훨씬 보기 쉽게 정리할 수 있게 되고, 기존엔 todo와 했던 task를 기록하려면 commit 기록을 던져넣고 claude한테 정리하라고 시켰었는데, 자연어로 매번 정리가 되어 있으니 해온 일과 앞으로 할 일에 대한 컨텍스트 정리가 더 명확해졌다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;markdown&quot;&gt;&lt;code&gt;## Project Management Guidelines
- 단계별로 todo를 작성해서 업무를 진행하고, 단계를 끝마칠때마다 요약 보고를 출력할 것. 모든 단계를 끝마치면 수정했던 모든 파일들과 어떤 로직을 추가했는지 등을 포함한 총 정리 보고를 할 것.
- todo 한 단계를 완료할 때마다 간략 보고를 출력해야 해.

## 통합된 문서화 및 추적 가이드라인

### 1. 기본 원칙
- 모든 대화와 파일을 수정할 때마다, **수정 목적과 수정 내용에 대한 기록**을 남깁니다.
- 모든 기록은 **한글로 작성**하는 것을 원칙으로 합니다.
- 단, 심각한 보안 사항이나 git에 올라가면 안 되는 사항(api key, password 등)들은 문서화하지 않고, 글로만 출력합니다.

### 2. 저장 위치 및 파일 형식
- 모든 작업 기록 파일은 `docs/daily_work_summary/` 폴더 내에 저장합니다.
- 파일명은 한국 표준시(KST) 기준 작업 날짜를 따라 `YYYY-MM-DD.md` 형식으로 생성합니다. (예: `2025-08-05.md`)
- 한 날짜의 모든 작업 내역은 **해당 날짜의 파일 하나에만 기록**하여 관리합니다.

### 3. 작업 절차 및 내용
- **(사전 확인)** 파일 수정 작업 시작 전, `docs/daily_work_summary/` 폴더에서 오늘 날짜에 해당하는 파일이 있는지 확인합니다.
    - 파일이 존재하면, 내용을 먼저 읽고 충돌이 발생하지 않도록 주의하며 이어서 기록을 추가합니다.
- **(내용 기록)** 파일 안에는 완료된 작업을 구분하여(chapter별) 다음 내용을 기록합니다.
    - **완료 시각**: 해당 작업이 완료된 시각을 한국 표준시(KST) 기준으로 명시합니다. (예: `21:30 KST`)
    - **수정 목적 및 내용**: 어떤 파일을 왜, 어떻게 수정했는지 구체적으로 서술합니다.
    - **(선택) Git 커밋 로그**: `git log` 확인 시 새로운 커밋이 있다면, 해당 커밋 내역을 요약하여 함께 작성합니다.

### 4. 시간 기준
- 문서에 기록되는 모든 시간은 **한국 표준시(Korean Standard Time)**를 기준으로 하며, 시간 뒤에 **'KST'**를 명시합니다.

&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이를 주위에 알려주고 써본 후기를 들어보니, 토큰 소모량이 너무 많아지고 요즘 claude code 업데이트 이후에 Claude.md에 적어놔도 잘 참고하지 않는다고 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 Claude code 명령어로 만들어두고, 어느 정도는 수동으로 입력하는 방법으로 이 문제를 해결 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. 요구사항 구체화 시키기&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컨텍스트량이 충분하지 않은 상태에서 바로 코드 수정을 시키면 너무 못 짠다. &lt;br /&gt;그런데 반대로 컨텍스트량이 충분히 많이 주어진 상황이라면 코드 수정을 시켰을 때 opus가 아닌 sonnet 모델이어도 코드 수정이 원하는 방향으로 매우 잘 짜여지는 것을 느꼈다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;요즘에는 plan mode로 계속 수정시키면서 구현 계획을 같이 짜는 시간이 80%, 실제 agent mode로 code를 수정하게 시키거나 plan에서 짜여진 코드 수정 계획 기반으로 내가 직접 코드를 수정하는 시간이 20% 이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;요구사항이 구체화되고 해당 요구사항을 만족시키기 위해 수정해야 하는 코드 부분이 좁혀지면서 plan의 컨텍스트가 충분해지는 시점이 오면 코드 짜는 건 사람이 짜나 AI가 짜나 큰 차이가 없는 것 같다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존에는 이 시점까지 도달하려면 다음의 긴 프로세스를 거쳐야 했다. 그런데 AI를 통해 병목 지점을 없앤다면 효율성이 올라가지 않을까? 라는 아이디어로 작업 중이다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;lt;기존 프로세스&amp;gt;&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;stakeholder의 막연한 요구사항&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그룹별 유저를 구분하고 싶어요. 그리고 그룹에 속하지 않은 유저만 삭제 가능하게 해주세요.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PM or 개발자의 요구사항 구체화&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;user에 대한 unsigned group 구분 추가, unsigned user만 삭제되고, 다른 user는 삭제되지 않게 하는 삭제 버튼을 추가해주세요&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;FE/BE 개발자의 구현 계획 세우기&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DB user table에 unsigned group 여부 나타내는 column 추가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;user table 관리, user API 호출하는 모듈&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;user 관리 page UI의 버튼 추가 위치, 삭제 버튼에 대한 로직&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;FE/BE 개발자 실제 구현 &amp;amp; 테스팅&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;먼저 코드 위치 찾기 &amp;rarr; 해당 코드에 추가될 로직 생각하기 &amp;rarr; api 추가, 클릭커블 버튼 추가&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;user table에서 unsigned 여부 확인 &amp;rarr; 삭제 가능한지 판단 및 삭제해주는 DELETE API 구현 &amp;rarr; 해당 API 호출하는 버튼 생성 &amp;rarr; 연결 후 테스트&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여기서 병목이 발생하던 지점은 다음과 같다.&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;요구사항 구체화&lt;/span&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PM이 있는 경우 커뮤니케이션 비용 발생&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PM이 없는 경우 개발자가 직접 요구사항을 구체화 해야하는 리소스 낭비 발생&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;구현 계획&lt;/span&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;매우 큰 코드베이스에서 특정 코드의 기존 구현 방법을 이해하는 시간&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이미 구현된 재사용 가능한 로직이 있을지 찾아보는 시간&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 구현 &amp;amp; 테스팅&lt;/span&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제 어느 부분에 구현해야 하는지 코드 위치를 찾는 데 걸리는 시간&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;로직 추가 이후 사이드 이펙트 없는지 검증 및 testing&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이를 정리해보면서 깨달았는데, 요구사항만 명확하면 구현하는 데에는 그리 큰 어려움이 없다는 것이다. 실제로 시간을 따져보아도 단순한 구현 시간보다 &amp;ldquo;어떻게&amp;rdquo; &amp;ldquo;잘&amp;rdquo; 구현할지 고민하고 자료를 찾아보는 시간이 훨씬 길었다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;그래서 Claude code와 같은 AI Agent를 이용해서 이 요구사항 구체화에 대한 병목을 줄이니까 구현에만 더 집중할 수 있어 업무 효율이 올라가는 경험을 했다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. 거대한 코드베이스에서 필요한 수정 부분 찾아내기&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;프롬프트 : &amp;ldquo;OOO에 관련된 구현을 하려고 하는데, 기존에 어느 부분에서 구현되어 있는지 찾아주고 어떤 방향으로 구현하면 좋을지 검토해줘&amp;rdquo;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;특정 코드 부분과 어느 부분에서 수정하면 좋을지 자주 찾아보았다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;기존에는 다른 사람들이 관리하던 거대한 코드베이스에서 내가 원하는 기능이 어디에 있는지, 또 이미 구현된 중복 모듈이 있지 않을지 찾아보는 시간이 꽤나 걸렸는데, AI Agent를 시키니 많은 부분이 자동화되어 너무 편해졌다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&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;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;5. 테스트 케이스 빠르게 만들어내기&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백엔드 API의 경우 requset data type과 response data type / code가 정해져 있기 때문에 AI를 사용하면 거의 대부분 자동으로 테스트 케이스들을 만들어 낼 수 있었다.&lt;/li&gt;
&lt;li&gt;프론트엔드의 경우 조금 더 복잡했는데, E2E 테스트나 화면에 대한 테스트를 완전히 자동으로 만들어 낼 수는 없었고 개발자의 더 명확한 지시나 많은 컨텍스트를 AI한테 주어야 했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&amp;lt;Agentic AI 후기들&amp;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;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;1편 :&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-1%ED%8E%B8-Claude-Code-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90&quot;&gt;2025.09.21 - [프로그래밍] - Agentic AI 후기 1편 : Claude Code 사용법 및 장단점&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2편 :&amp;nbsp;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-2%ED%8E%B8-Claude-Code-%ED%95%9C-%EB%8B%AC-%EC%82%AC%EC%9A%A9-%ED%8C%A8%ED%84%B4-%EB%B6%84%EC%84%9D&quot;&gt;2025.09.21 - [프로그래밍] - Agentic AI 후기 2편 : Claude Code 한 달 사용 패턴 분석&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3편 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #0070d1; text-align: start;&quot; href=&quot;https://turtle-hwan.tistory.com/entry/Agentic-AI-%ED%9B%84%EA%B8%B0-3%ED%8E%B8-%EC%8B%A4%ED%97%98%EC%A0%81%EC%9C%BC%EB%A1%9C-%EC%95%8C%EC%95%84%EB%82%B8-Claude-Code-%ED%99%9C%EC%9A%A9-%EA%B7%B9%EB%8C%80%ED%99%94-%EC%A0%84%EB%9E%B5-5%EA%B0%80%EC%A7%80&quot;&gt;2025.10.20 - [분류 전체보기] - Agentic AI 후기 3편 : 실험적으로 알아낸 Claude Code 활용 극대화 전략 5가지&lt;/a&gt;&lt;/p&gt;</description>
      <category>프로그래밍</category>
      <category>agentic ai</category>
      <category>Claude code 활용</category>
      <category>프롬프트 엔지니어링</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/34</guid>
      <comments>https://turtle-hwan.tistory.com/entry/Agentic-AI-%ED%9B%84%EA%B8%B0-3%ED%8E%B8-%EC%8B%A4%ED%97%98%EC%A0%81%EC%9C%BC%EB%A1%9C-%EC%95%8C%EC%95%84%EB%82%B8-Claude-Code-%ED%99%9C%EC%9A%A9-%EA%B7%B9%EB%8C%80%ED%99%94-%EC%A0%84%EB%9E%B5-5%EA%B0%80%EC%A7%80#entry34comment</comments>
      <pubDate>Mon, 20 Oct 2025 21:14:41 +0900</pubDate>
    </item>
    <item>
      <title>Agentic AI 후기 2편 : Claude Code 한 달 사용 패턴 분석</title>
      <link>https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-2%ED%8E%B8-Claude-Code-%ED%95%9C-%EB%8B%AC-%EC%82%AC%EC%9A%A9-%ED%8C%A8%ED%84%B4-%EB%B6%84%EC%84%9D</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이전 편 :&amp;nbsp;&lt;a href=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-1%ED%8E%B8-Claude-Code-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.09.21 - [프로그래밍] - Agentic AI 후기 1편 : Claude Code 사용법 및 장단점&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 편 :&amp;nbsp;&lt;a href=&quot;https://turtle-hwan.tistory.com/entry/Agentic-AI-%ED%9B%84%EA%B8%B0-3%ED%8E%B8-%EC%8B%A4%ED%97%98%EC%A0%81%EC%9C%BC%EB%A1%9C-%EC%95%8C%EC%95%84%EB%82%B8-Claude-Code-%ED%99%9C%EC%9A%A9-%EA%B7%B9%EB%8C%80%ED%99%94-%EC%A0%84%EB%9E%B5-5%EA%B0%80%EC%A7%80&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.10.20 - [분류 전체보기] - Agentic AI 후기 3편 : 실험적으로 알아낸 Claude Code 활용 극대화 전략 5가지&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;claude_code_usage2.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTbQPq/dJMb9P0GtM2/MUqerC6KoKG2bEk7VR8tkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTbQPq/dJMb9P0GtM2/MUqerC6KoKG2bEk7VR8tkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTbQPq/dJMb9P0GtM2/MUqerC6KoKG2bEk7VR8tkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTbQPq%2FdJMb9P0GtM2%2FMUqerC6KoKG2bEk7VR8tkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;375&quot; data-filename=&quot;claude_code_usage2.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;AI Agent vs Agentic AI&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 블로그에 Agent AI라고 적어두었는데, 이는 없는 단어가 아니냐는 피드백이 있었다. 사실 용어를 쓰면서도 잘 모르고 있었기에 잘 찾아보지도 않고 사용한 것에 반성하며 조사하여 정리해본다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아직 Agent 분야로 나아가는 중이라 용어 정립이 잘 되지 않은 상태인 것 같다. Google Scholar 기준 AI Agent, Agentic AI, Agent AI 세 용어 모두 쓰이고는 있었으며, AI Agents~ 라는 용어가 가장 많이 쓰이고 Agentic AI가 그 다음으로 많이 쓰이는 것을 볼 수 있었다.&lt;/li&gt;
&lt;li&gt;구글에서는 자율성을 기준으로 AI Agent, AI Assistant, AI Bot 으로 구분하는 것 같고, 최근 들어 목표 수립까지 AI가 스스로 할 정도의 완전한 자율성을 가진 AI를 지칭하기 위해 Agentic 이라는 용어를 사용하기 시작한 것으로 보인다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;AI Agent란?&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Goal &amp;rarr; Agent &amp;rarr; Tools &amp;rarr; Output&lt;/p&gt;
&lt;/blockquote&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; 대신하여 자율적으로 행동하는 AI 소프트웨어 시스템&lt;/li&gt;
&lt;li&gt;추론, 계획, 기억이 가능하며 자율적으로 의사 결정, 학습, 조정을 처리한다.&lt;/li&gt;
&lt;li&gt;멀티모달 정보 처리가 가능하고, 다른 Agent와 협력하는 것도 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Agentic AI?&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Objective &amp;rarr; Goals &amp;rarr; Sub-Agents &amp;rarr; Tools + Memory &amp;rarr; Output&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스스로 목표를 설정하고, 그 목표 달성을 위한 전략을 수립하며, 적절한 Tool을 사용해 문제를 해결해나가며 목표를 달성하는 AI 소프트웨어 시스템&lt;/li&gt;
&lt;li&gt;여러 AI Agents를 통제 가능하고, 결과를 모아 능동적으로 분석 가능&lt;/li&gt;
&lt;li&gt;즉, MCP와 같은 tool들을 자율적으로 선택해 사용 가능하며 스스로 코드르 짜고 문제 해결하며 디버깅까지 가능한 Claude Code, Gemini CLI, OpanAI Codex 와 같은 도구들은 Agentic AI라 볼 수 있을 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고 사이트들&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://modulabs.co.kr/blog/ai-agent-vs-agentic-ai&quot;&gt;https://modulabs.co.kr/blog/ai-agent-vs-agentic-ai&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Google Cloud AI Agent : &lt;a href=&quot;https://cloud.google.com/discover/what-are-ai-agents&quot;&gt;https://cloud.google.com/discover/what-are-ai-agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;1001개의 gen AI 사용 사례 : &lt;a href=&quot;https://cloud.google.com/transform/101-real-world-generative-ai-use-cases-from-industry-leaders?hl=en&quot;&gt;https://cloud.google.com/transform/101-real-world-generative-ai-use-cases-from-industry-leaders?hl=en&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Gen AI Agent 개발자들을 위한 가이드라인 : &lt;a href=&quot;https://www.kaggle.com/whitepaper-agent-companion&quot;&gt;https://www.kaggle.com/whitepaper-agent-companion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;삼성 SDS Agentic AI 설명 : &lt;a href=&quot;https://www.samsungsds.com/kr/insights/agentic-ai-the-autonomous-era-of-artificial-intelligence.html&quot;&gt;https://www.samsungsds.com/kr/insights/agentic-ai-the-autonomous-era-of-artificial-intelligence.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실제 사용했던 패턴 정리&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.claude/ 폴더의 이전 대화 내역을 claude code한테 읽게 시키고, 가장 많이 사용했던 명령 패턴을 정리해 달라고 시켰더니 다음과 같이 나왔다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 ~해줘 라고 던진 것이 많은 것 같아 좀 반성하게 된다. 더 많은 컨텍스트를 주고 더 작은 단위로 시켜서 효과적으로 결과를 뽑아야 하는데 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 단순한 접근보단 문제를 단계별로 쪼개어 접근한 내역이 많고, 바로 시키기보단 구현 계획 &amp;rarr; 검토 &amp;rarr; 코드 구현 방향으로 주로 사용한 것 같아 다행이라는 생각이 든다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;앞으로도 전체 과정을 AI한테 위임하기 보다는&lt;b&gt; 단계를 쪼개고 각 단계별로 명확한 지침을 주면서 사람의 검토와 함께 위임&lt;/b&gt;해야 훨씬 효율이 좋을 것이다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;가장 많이 사용하는 AI 명령 패턴 정리(500+ 대화 기록 기반) :   상위 10개 명령 패턴&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&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;&quot;OOO한 곳에서 OOO 한 코드를 찾아줘&quot;&lt;/li&gt;
&lt;li&gt;&quot;여기서 OOO 부분을 수정해줘&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;API 엔드포인트 구현/수정
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;API를 구현 계획 세워줘&quot;&lt;/li&gt;
&lt;li&gt;&quot;엔드포인트 수정 방향 알려줘&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;시스템 상태 확인 및 문제 해결
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;연결이 잘 되는지 확인해줘&quot;&lt;/li&gt;
&lt;li&gt;&quot;연결 안 되는 문제 원인 파악해줘&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;테스트 작성 및 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;테스트해줘&quot;&lt;/li&gt;
&lt;li&gt;&quot;통과 안 된 test case 수정해줘&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DB 관련 작업
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;DB에서 특정 데이터 조회하는 쿼리 만들어줘&quot;&lt;/li&gt;
&lt;li&gt;&quot;데이터베이스 수정 방향성 제시해줘&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;GitHub/버전 관리 조회
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;어느 커밋에서 이 작업이 진행되었는지 찾아줘&quot;&lt;/li&gt;
&lt;li&gt;&quot;기록을 뒤져서 찾아줘&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;설정 값 변경 및 최적화
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;설정을 변경해줘&quot;&lt;/li&gt;
&lt;li&gt;&quot;최적화 하는 방법 알려줘&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;계획 수립 후 구현
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;위 계획대로 구현해줘&quot;&lt;/li&gt;
&lt;li&gt;&quot;기존 코드베이스를 유지하면서 구현해줘&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Docker/인프라 작업
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;Docker 설정 수정 알려줘&quot;&lt;/li&gt;
&lt;li&gt;&quot;환경 설정 방법 알려줘&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;통합 분석 및 패턴 조회
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;지금까지의 기록을 정리해줘&quot;&lt;/li&gt;
&lt;li&gt;&quot;가장 많이 명령하는 패턴들을 정리해줘&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;공통 특징&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;명령어 종료: &quot;~해줘&quot; 형식 사용&lt;/li&gt;
&lt;li&gt;구체적 지시: 파일명, 함수명, API 경로 등 구체적 언급&lt;/li&gt;
&lt;li&gt;단계적 접근: 찾기 &amp;rarr; 분석 &amp;rarr; 수정 순서&lt;/li&gt;
&lt;li&gt;문제 해결 중심: 에러/버그 해결 요청이 많음&lt;/li&gt;
&lt;li&gt;기록 참조: 과거 작업/커밋 히스토리 추적 패턴&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;공통 명령 진행 순서&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 인식 &amp;rarr; &quot;확인해줘&quot; &lt;br /&gt;&amp;darr; &lt;br /&gt;원인 분석 &amp;rarr; &quot;왜 이렇게 되는지 찾아줘&quot; &lt;br /&gt;&amp;darr; &lt;br /&gt;해결 방안 &amp;rarr; &quot;이렇게 수정해줘&quot; &lt;br /&gt;&amp;darr; &lt;br /&gt;검증 요청 &amp;rarr; &quot;테스트해줘&quot; &lt;br /&gt;&amp;darr; &lt;br /&gt;최종 확인 &amp;rarr; &quot;잘 작동하는지 확인해줘&quot;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;일반적인 문제 해결 패턴 분석 (대화 기록 기반)&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;디버깅 진행 패턴 :&amp;nbsp;체계적인 정보 수집 &amp;rarr; 가설 검증 &amp;rarr; 해결책 구현&lt;/li&gt;
&lt;li&gt;기능 구현 플로우 :&amp;nbsp;요구사항 &amp;rarr; 계획 &amp;rarr; 점진적 개발 &amp;rarr; 테스트 &amp;rarr; 배포&lt;/li&gt;
&lt;li&gt;최적화 접근 방법 :&amp;nbsp;기준점 측정 &amp;rarr; 프로파일링 &amp;rarr; 목표 최적화 &amp;rarr; 검증&lt;/li&gt;
&lt;li&gt;설정 문제 해결 :&amp;nbsp;감사 &amp;rarr; 검증 &amp;rarr; 점진적 수정&lt;/li&gt;
&lt;li&gt;코드 리팩토링 패턴 :&amp;nbsp;분석 &amp;rarr; 계획 &amp;rarr; 단계별 수정 &amp;rarr; 검증&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Claude Code 프롬프트 최적화 및 개선 방안&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 지금 해왔던 프롬프트를 어떤 방향으로 개선시켜야 할지, 더 좋은 결과를 뽑아낼 방안이 있을지 조사해보았다. &lt;br /&gt;&lt;b&gt;&lt;br /&gt;어떤 문장을 쓸까? 보다 어떻게 구조화할까?&lt;/b&gt; 가 더 중요하다고 한다. &lt;br /&gt;&lt;br /&gt;어차피 LLM은 토큰화 된 값의 연관관계로만 판단하므로 단어와 문장 내용을 개선하기보다 &lt;b&gt;구분자&lt;/b&gt;를 통해 특정 문장이 어느 내용인지를 확실하게 알려주는 것이 성능에 좋기 때문인 것 같다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 Claude Code한테 물어보고 공식 문서(&lt;a href=&quot;https://docs.claude.com/ko/docs/build-with-claude/prompt-engineering/prompt-improver&quot;&gt;https://docs.claude.com/ko/docs/build-with-claude/prompt-engineering/prompt-improver&lt;/a&gt;)를 참고했을 때는 &lt;b&gt;XML 문법&lt;/b&gt;을 통해 각 문장을 구분해주면 좋다고 답했다. 그런데 사람이 매번 prompt 칠 때마다 XML로 구분자까지 넣어주기엔 너무 불편하지 않은가..!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 추가로 알아보니 &lt;b&gt;markdown&lt;/b&gt;으로도 비슷한 구분자 효과를 낼 수 있다는 걸 알게 되었다. XML 태그, 마크다운 헤더와 같은 별도 구분자를 통해 AI Attention mechanism에게 말뭉치 블럭이 어떤 개념인지 확실하게 알려주는 지표 역할을 하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 이야기가 나오는 robot.txt의 llm 버전인 llms.txt의 구조도 markdown으로 작성하는 것과 비슷한 논지인 것 같다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;XML Prompt 예시&lt;/h4&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;  &amp;lt;instructions&amp;gt;
    &amp;lt;docker&amp;gt;docker compose 명령어 사용&amp;lt;/docker&amp;gt;
    &amp;lt;documentation&amp;gt;작업 내용 한글 기록&amp;lt;/documentation&amp;gt;
  &amp;lt;/instructions&amp;gt;

  &amp;lt;constraints&amp;gt;
    보안 정보는 문서화 금지 (API keys, passwords)
  &amp;lt;/constraints&amp;gt;

  &amp;lt;role&amp;gt;
  Python 백엔드 엔지니어로서 코드 품질과 문서화 중시
  &amp;lt;/role&amp;gt;
  
  &amp;lt;conditional_rules&amp;gt;
    &amp;lt;if condition=&quot;DB 변경&quot;&amp;gt;
      - /database/erd.md 업데이트
      - /database/backups에 백업 생성
    &amp;lt;/if&amp;gt;
    &amp;lt;if condition=&quot;코드 변경&quot;&amp;gt;
      - readme.md, requirement.md 동기화
    &amp;lt;/if&amp;gt;
  &amp;lt;/conditional_rules&amp;gt;

  &amp;lt;prohibitions&amp;gt;
    - 불필요한 문서 생성 금지
    - 보안 정보 문서화 금지
    - 미승인 git commit 금지
  &amp;lt;/prohibitions&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Markdown Prompt 예시&lt;/h4&gt;
&lt;pre class=&quot;python&quot; data-ke-language=&quot;python&quot;&gt;&lt;code&gt;## 역할
Python 백엔드 엔지니어로서 코드 품질과 문서화 중시

## 지시사항
* docker compose 명령어 사용
* 작업 내용 한글 기록

## 제약 조건
* 보안 정보는 문서화 금지 (API keys, passwords)

## 조건부 규칙
* **DB 변경 시:**
    * `/database/erd.md` 업데이트
    * `/database/backups`에 백업 생성
* **코드 변경 시:**
    * `readme.md`, `requirement.md` 동기화

## 금지 사항
* 불필요한 문서 생성 금지
* 보안 정보 문서화 금지
* 미승인 git commit 금지&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;어떤 문장을 쓸지보다 어떻게 &lt;b&gt;구조화&lt;/b&gt;할지가 더 중요하다. &lt;br /&gt;&lt;b&gt;구분자&lt;/b&gt;를 써서 LLM에게 문장 연관 관계를 확실히 알려주자!!&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style5&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&amp;lt;Agentic AI 후기들&amp;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;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;1편 :&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-1%ED%8E%B8-Claude-Code-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90&quot;&gt;2025.09.21 - [프로그래밍] - Agentic AI 후기 1편 : Claude Code 사용법 및 장단점&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;2편 :&amp;nbsp;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-2%ED%8E%B8-Claude-Code-%ED%95%9C-%EB%8B%AC-%EC%82%AC%EC%9A%A9-%ED%8C%A8%ED%84%B4-%EB%B6%84%EC%84%9D&quot;&gt;2025.09.21 - [프로그래밍] - Agentic AI 후기 2편 : Claude Code 한 달 사용 패턴 분석&lt;/a&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;3편 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #0070d1; text-align: start;&quot; href=&quot;https://turtle-hwan.tistory.com/entry/Agentic-AI-%ED%9B%84%EA%B8%B0-3%ED%8E%B8-%EC%8B%A4%ED%97%98%EC%A0%81%EC%9C%BC%EB%A1%9C-%EC%95%8C%EC%95%84%EB%82%B8-Claude-Code-%ED%99%9C%EC%9A%A9-%EA%B7%B9%EB%8C%80%ED%99%94-%EC%A0%84%EB%9E%B5-5%EA%B0%80%EC%A7%80&quot;&gt;2025.10.20 - [분류 전체보기] - Agentic AI 후기 3편 : 실험적으로 알아낸 Claude Code 활용 극대화 전략 5가지&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>프로그래밍</category>
      <category>agentic ai</category>
      <category>ai agent</category>
      <category>claude code</category>
      <category>prompt 최적화</category>
      <category>xml prompt</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/32</guid>
      <comments>https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-2%ED%8E%B8-Claude-Code-%ED%95%9C-%EB%8B%AC-%EC%82%AC%EC%9A%A9-%ED%8C%A8%ED%84%B4-%EB%B6%84%EC%84%9D#entry32comment</comments>
      <pubDate>Mon, 20 Oct 2025 00:02:38 +0900</pubDate>
    </item>
    <item>
      <title>Agentic AI 후기 1편 : Claude Code 사용법 및 장단점</title>
      <link>https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-1%ED%8E%B8-Claude-Code-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;다음 편 :&amp;nbsp;&lt;a href=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-2%ED%8E%B8-Claude-Code-%ED%95%9C-%EB%8B%AC-%EC%82%AC%EC%9A%A9-%ED%8C%A8%ED%84%B4-%EB%B6%84%EC%84%9D&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.09.21 - [프로그래밍] - Agentic AI 후기 2편 : Claude Code 한 달 사용 패턴 분석&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;claude_code_usage1.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVgSb1/dJMb9PsPBL7/Sr3uYH8X6fX0LrTdh1KmG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVgSb1/dJMb9PsPBL7/Sr3uYH8X6fX0LrTdh1KmG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVgSb1/dJMb9PsPBL7/Sr3uYH8X6fX0LrTdh1KmG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVgSb1%2FdJMb9PsPBL7%2FSr3uYH8X6fX0LrTdh1KmG0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;375&quot; data-filename=&quot;claude_code_usage1.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;들어가며&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;요즘 주위에서 Claude Code, Gemini CLI, OpenAI Codex 까지 다양한 CLI 기반 Coding Agentic AI 가 많이 등장했고, 유저가 빠르게 느는 것이 보인다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;올해 초 까지만 해도 GItHub copilot부터 시작해 Windsurf, Cursor로 이어지는 AI Agent Editor가 열풍이었는데 CLI가 나오더니 유행이 정말 순식간에 바뀌어버렸다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;주변의 MCP, AI Agent에 관심 많은 지인 개발자들도 몇 번 클로드 코드 쓰더니 맛들려서 요금제 올리고 싶어하더라...!&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;style3&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Claude Code 사용 계기&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;현재 근무하는 스타트업이 아무래도 AI 회사고, LLM 관련 업무를 많이 하다보니 각종 LLM을 많이 경험해보라 권유하는 분위기다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;원래는 GitHub Copilot 학생 계정으로만 사용 중이었는데 마침 회사에서 Claude Code MAX $200도 사줘서 토큰도 넉넉하겠다, 근 1~2달 동안 Claude Code를 신나게 써봤다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;npx ccusage 로 측정한 한 달 동안 사용한 비용은 $2359로 꽤 많이 썼다. opus 모델 때문에 사용량이 뻥튀기된 감이 있다. 실제론 API가 아닌 MAX 로그인 토큰의 구독 요금제인 월 $200 안에서 모두 해결된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;사용 초기에는 5h limit에 자주 걸렸는데, 최근 업데이트 이후에는 체감 성능은 많이 떨어진 대신 토큰 limit에는 한 번도 안 걸렸다.&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;1121&quot; data-origin-height=&quot;1363&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biyDLa/btsQIZI8KdI/K7RLf8zUfF16Uvlsh8ZTuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biyDLa/btsQIZI8KdI/K7RLf8zUfF16Uvlsh8ZTuK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biyDLa/btsQIZI8KdI/K7RLf8zUfF16Uvlsh8ZTuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiyDLa%2FbtsQIZI8KdI%2FK7RLf8zUfF16Uvlsh8ZTuK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1121&quot; height=&quot;1363&quot; data-origin-width=&quot;1121&quot; data-origin-height=&quot;1363&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Claude Code 사용법&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;Claude Code, Gemini cli, OpenAI Codex 모두 기본적인 사용법은 동일히다. npm package로 모두 제공 중이라, 다음 명령어로 npm package를 설치하고 명령줄에서 실행만 하면 된다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;terminal에서 실행하면 별도의 node.js 기반 스레드를 띄워 작동하는 것으로 보인다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;터미널 명령어를 통해 코드나 파일에 접근하고 이를 바로 LLM에 source로 넣을 수 있어 웹 LLM에서 코드 복붙하는 것 보다는 훨씬 편하다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;npm install -g @anthropic-ai/claude-code&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://claude.com/product/claude-code&quot;&gt;https://claude.com/product/claude-code&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;npm install -g @google/gemini-cli&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/google-gemini/gemini-cli&quot;&gt;https://github.com/google-gemini/gemini-cli&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;npm i -g @openai/codex&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://github.com/openai/codex&quot;&gt;https://github.com/openai/codex&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;설치 이후, 터미널에 claude 라 치면 LLM과 채팅할 수 있는 화면이 나온다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;/command 처럼 앞에 /를 붙여 명령어를 입력 가능하다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;/init 을 통해 claude가 repo를 읽고, 자동으로 claude.md 지침을 생성하게 할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;@를 붙여 특정 파일에 대한 컨텍스트를 줄 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;#를 붙여 claude.md에 기록시키고, claude가 항상 이를 참조하게 할 수 있다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;1001&quot; data-origin-height=&quot;534&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2XTGW/btsQHYjIQx5/OgkR9zTEJ8G7oqY7JIxkC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2XTGW/btsQHYjIQx5/OgkR9zTEJ8G7oqY7JIxkC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2XTGW/btsQHYjIQx5/OgkR9zTEJ8G7oqY7JIxkC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2XTGW%2FbtsQHYjIQx5%2FOgkR9zTEJ8G7oqY7JIxkC1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;427&quot; data-origin-width=&quot;1001&quot; data-origin-height=&quot;534&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Claude Code 사용량 측정 및 원리&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;npx ccusage 를 통해 간편하게 사용량을 측정할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://ccusage.com/&quot;&gt;https://ccusage.com/&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;사용량 측정의 원리가 궁금하여 간단히 찾아보았다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;~/.claude/ 사용자 루트 경로에 claude 설정 파일들이 많았고, projects/ 폴더 안에서 지금까지의 대화 내역을 모두 jsonl 파일로 저장하고 있다!!!&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;그러면 이 로그를 tokenizer만 돌려서 토큰량 계산해주면 되는 것이다!!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;929&quot; data-origin-height=&quot;71&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2HxNU/btsQGDt9a8G/l9paNFKDp6psGThJFegF51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2HxNU/btsQGDt9a8G/l9paNFKDp6psGThJFegF51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2HxNU/btsQGDt9a8G/l9paNFKDp6psGThJFegF51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2HxNU%2FbtsQGDt9a8G%2Fl9paNFKDp6psGThJFegF51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;929&quot; height=&quot;71&quot; data-origin-width=&quot;929&quot; data-origin-height=&quot;71&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;Claude Code 장단점&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;장점&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;사용하면서 느낀 가장 큰 장점은 거대한 코드베이스가 있을 때, 내가 원하는 기능을 구현하려면 어느 부분에 구현해야 할지 &lt;b&gt;코드 위치를 찾는 시간&lt;/b&gt;이 엄청 단축되었다는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;아무리 폴더, 파일 구조화를 잘 해두어도 코드에 대한 컨텍스트가 없는 사람이 바로 기능을 구현하기가 쉽지 않은데, 이 시간이 줄어들어 정말 좋았다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;단점&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;단점은 코드를 짜는 것마저도 claude code를 시켜버리면 직접 구현하지 않아서 &lt;b&gt;어느 부분을 어떻게 수정했는지에 대한 컨텍스트가 없어&lt;/b&gt; 나중에도 결국 AI Agent에 의존하게 되는 걸 많이 느꼈다. 마치 조수석에 타면 직접 운전할 때보다 길을 훨씬 못 기억하는 것처럼 말이다.&lt;/span&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Nanum Gothic';&quot;&gt;후기&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;원래는 하나의 글에 다 집어넣으려다 글이 너무 길어져서 &lt;s&gt;2편도 아니고&lt;/s&gt; 3편이나 분리하게 되었다.&lt;br /&gt;먼저 이번 글에서 사용법이랑 장단점을 간단하게 정리하고, 2편에서 직접 한 달간 사용한 자료로 패턴을 분석해보고, 3편에서 이를 기반으로 실험적으로 알게 된 Claude Code를 어떻게 하면 더 잘 사용할 수 있는지를 체계화해서 정리해 보았다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #666666;&quot;&gt;아직까지 완벽하지도 않고 실수도 많지만 지불하는 돈 이상의 가치는 충분히 얻고 있다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR'; color: #666666;&quot;&gt;게다가 말 그대로 Agent, 도우미로서의 효율이 엄청나서 더욱더 잘 사용하고 싶다는 생각이 든다.&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&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;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;&amp;lt;Agentic AI 후기들&amp;gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Nanum Gothic'; color: #000000;&quot;&gt;1편 :&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-1%ED%8E%B8-Claude-Code-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.09.21 - [프로그래밍] - Agentic AI 후기 1편 : Claude Code 사용법 및 장단점&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2편 :&amp;nbsp;&lt;a href=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-2%ED%8E%B8-Claude-Code-%ED%95%9C-%EB%8B%AC-%EC%82%AC%EC%9A%A9-%ED%8C%A8%ED%84%B4-%EB%B6%84%EC%84%9D&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.09.21 - [프로그래밍] - Agentic AI 후기 2편 : Claude Code 한 달 사용 패턴 분석&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3편 : &lt;a style=&quot;background-color: #e6f5ff; color: #0070d1; text-align: start;&quot; href=&quot;https://turtle-hwan.tistory.com/entry/Agentic-AI-%ED%9B%84%EA%B8%B0-3%ED%8E%B8-%EC%8B%A4%ED%97%98%EC%A0%81%EC%9C%BC%EB%A1%9C-%EC%95%8C%EC%95%84%EB%82%B8-Claude-Code-%ED%99%9C%EC%9A%A9-%EA%B7%B9%EB%8C%80%ED%99%94-%EC%A0%84%EB%9E%B5-5%EA%B0%80%EC%A7%80&quot;&gt;2025.10.20 - [분류 전체보기] - Agentic AI 후기 3편 : 실험적으로 알아낸 Claude Code 활용 극대화 전략 5가지&lt;/a&gt;&lt;/p&gt;</description>
      <category>프로그래밍</category>
      <category>agentic ai</category>
      <category>ai agent</category>
      <category>claude code</category>
      <category>claude code 장단점</category>
      <category>claude code 후기</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/31</guid>
      <comments>https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-1%ED%8E%B8-Claude-Code-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90#entry31comment</comments>
      <pubDate>Sun, 21 Sep 2025 18:48:05 +0900</pubDate>
    </item>
    <item>
      <title>Google I/O Extended Incheon 2025 후기와 감상</title>
      <link>https://turtle-hwan.tistory.com/entry/Google-IO-Extended-Incheon-2025-%ED%9B%84%EA%B8%B0</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock style1&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;google_io_extend.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Hn4Gk/btsQzi3buvF/bLpRcosawtgbGrCylVrKvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Hn4Gk/btsQzi3buvF/bLpRcosawtgbGrCylVrKvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Hn4Gk/btsQzi3buvF/bLpRcosawtgbGrCylVrKvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHn4Gk%2FbtsQzi3buvF%2FbLpRcosawtgbGrCylVrKvk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;768&quot; data-filename=&quot;google_io_extend.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-size=&quot;size26&quot; data-ke-style=&quot;style1&quot;&gt;들어가며&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2025년 7월 26일 (토) 에 열린 GDG Incheon에서 주관한 Google I/O Extended Incheon 2025 행사에 다녀오게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GDGoC Konkuk 소속으로 활동 중이기도 하고, 지인이 발표해서 구경할 겸 인사이트도 얻을 겸 친구들이랑 갔었다.&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. 1인 개발 서비스를 위한 Gemini CLI 사용기 - 이준범 (AI GDE)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;10만 명 이상 사용자를 보유한 스마트 스팸 필터 앱을 1인 개발로 직접 만들고 유지 보수 하면서 Gemini CLI Agent를 적극적으로 이용한 경험을 공유해 주셨다. &lt;br /&gt;현재 다니는 회사에서도 Claude Code를 적극적으로 이용하고 있어서 다른 사람의 Agent AI 이용 방법이 궁금해져 들었다.&lt;/p&gt;
&lt;/blockquote&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;요즘 LLM은 판단도 잘해주지만, LLM은 비싸고 느리다. &amp;rarr; SLM (Small Language Model) 이용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;작은 모델을 직접 학습시키기 위해서 기존 자신의 휴대폰에 있던 스팸 메시지와 정상 메시지 15,000 개를 이용&lt;/li&gt;
&lt;li&gt;LLM으로 먼저 판단하여 분류하고, 더 높은 정확도를 위해 GPT, Claude, Gemini 등 여러 상용 LLM 사용하고 결과에 Voting 알고리즘 적용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;준범님이 스팸 필터 서비스를 1인 개발하며 문제 해결에 도달한 방식이 현재 회사에서 고민하여 도달한 프로덕트와 방향성이 일치해서 매우 놀라웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 보안 서비스를 개발 중인데, 기존 보안에서 단순 Regex로 걸러내거나 단어 기반 차단 방식은 오탐률이 너무 높다는 문제가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이를 개선하기 위해 Regex에 LLM을 더해 판단시키면 문맥 상의 위험한 주제나 PII도 잘 검출할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 GPT 등 상용 LLM API 를 연결해서 사용해 보면 일단 응답 속도가 최소 500ms 이상으로 너무 느리고, API 가격이 너무 비싸다. 따라서 직접 파인튠한 SLM으로 판단시키면 가격도 싸고 속도도 300ms 이하로 유지할 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;처음엔 isSpam 1개 판단 기준이었지만, 5단계 json output으로 변경했다. 매우 높음 / 높음 / 중간 / 낮음 / 매우 낮음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오히려 0~100 사이 숫자 확률 분포보다 자연어로 적은 단계를 매겨서 출력하게 프롬프트를 주는 것이 더 효과적이라 하셨다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Spam인데 Spam이 아니라 하는 False negative / Spam이 아닌데 Spam이라 하는 False positive 모두 잡아야 한다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Fuzzy Cache - 모두 Exact Match Cache는 낮으므로, Vector DB (postgresql의 PG Vector)를 통한 L2 distance 유사도 비교를 진행했으며, 임베딩이 LM 모델보다 훨씬 빠르다.&lt;/li&gt;
&lt;li&gt;DB에 쌓이는 것 중 유사한 문장을 묶어서 임베딩 후 mean vector에 스팸 / 정상 라벨을 달아서 써먹는다는 아이디어&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;GEMINI.md를 필수로 만들어야 필요없는 editing 줄어든다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Build &amp;amp; Fix Bugs 꼭 넣기&lt;/li&gt;
&lt;li&gt;기능 추가하면서 markdown 체크박스로 관리&lt;/li&gt;
&lt;li&gt;단위 모듈 별 세션 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이건 현재 회사에서 작업할때도 쏠쏠히 써먹는 방식이다. Claude Code를 어떻게 잘 사용하는지는 아래 글에서 더 자세히 작성해두었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-1%ED%8E%B8-Claude-Code-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2025.09.21 - [프로그래밍] - Agent AI 후기 1편 : Claude Code 사용법 및 장단점&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1758813470423&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;Agent AI 후기 1편 : Claude Code 사용법 및 장단점&quot; data-og-description=&quot;다음 편 : 2025.09.21 - [프로그래밍] - Agent AI 후기 2편 : Claude Code 한 달 사용 패턴 분석들어가며요즘 주위에서 Claude Code, Gemini CLI, OpenAI Codex 까지 다양한 CLI 기반 Coding Agent AI 가 많이 등장했고, 유저&quot; data-og-host=&quot;turtle-hwan.tistory.com&quot; data-og-source-url=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-1%ED%8E%B8-Claude-Code-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90&quot; data-og-url=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-1%ED%8E%B8-Claude-Code-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bwodcT/hyZJTfcHLD/KbzCpVswJeVoKXaa2uWbo1/img.png?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/G3Dst/hyZJPqkeYt/yzu4i8KcWQZDJbX9A3mzHK/img.png?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/cuARrY/hyZJBs1sCU/xy3kIykZrLcb5SSHWDJnX0/img.png?width=1121&amp;amp;height=1363&amp;amp;face=0_0_1121_1363&quot;&gt;&lt;a href=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-1%ED%8E%B8-Claude-Code-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://turtle-hwan.tistory.com/entry/Agent-AI-%ED%9B%84%EA%B8%B0-1%ED%8E%B8-Claude-Code-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%B0%8F-%EC%9E%A5%EB%8B%A8%EC%A0%90&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bwodcT/hyZJTfcHLD/KbzCpVswJeVoKXaa2uWbo1/img.png?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/G3Dst/hyZJPqkeYt/yzu4i8KcWQZDJbX9A3mzHK/img.png?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/cuARrY/hyZJBs1sCU/xy3kIykZrLcb5SSHWDJnX0/img.png?width=1121&amp;amp;height=1363&amp;amp;face=0_0_1121_1363');&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;Agent AI 후기 1편 : Claude Code 사용법 및 장단점&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;다음 편 : 2025.09.21 - [프로그래밍] - Agent AI 후기 2편 : Claude Code 한 달 사용 패턴 분석들어가며요즘 주위에서 Claude Code, Gemini CLI, OpenAI Codex 까지 다양한 CLI 기반 Coding Agent AI 가 많이 등장했고, 유저&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;turtle-hwan.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;전체적으로 AI와 기반 지식들을 잘 가져와서 조합하면서 문제 해결에 도달한 방식이 매우 인상적이었다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 대규모 트래픽을 처리하는 프론트 개발자의 전략 - 이승민(마량)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;티켓팅 플랫폼 티켓타코를 개발하며 대규모 트래픽을 견디면서 정합성을 보장하고 오버부킹을 방지하는 방법을 설명해 주셨다. 프론트 개발자로 풀스택을 간단히 하기 좋은 스택인 Next.js + Supabase를 선택하셨다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연하게도 트래픽 처리를 위한 DB 얘기가 절반 이상이었지만 요즘 Next.js 기반에 FastAPI, Supabase까지 개발하면서 필요성을 느끼던 차라 좋았다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 8년 넘게 개발 블로그를 하면서 깨달은 것들 - 변성윤(글또)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;꾸준히 하는 사람은 적다.&lt;br /&gt;매우 격하게 공감한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Part 1. 마음가짐. 글쓰기에 대한 생각들&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;글을 쓰는 것에 저항감
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;글을 써도 되나?&lt;/li&gt;
&lt;li&gt;글을 작성해도 만족스럽지 않다&lt;/li&gt;
&lt;li&gt;소재가 떠오르지 않는다&lt;/li&gt;
&lt;li&gt;계속 쓰는 것이 어렵다&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;왜 블로그를 만들었는지 이유를 다시 되새겨 보자.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;남이 아니라 나를 위한 글&lt;/li&gt;
&lt;li&gt;반복을 줄이기 위한 글&lt;/li&gt;
&lt;li&gt;배운 것을 까먹지 않기 위한 글&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 블로그에 정리하고 내가 볼 거면 NotebookLM처럼 BlogLM으로 blog 글 sitemap 기반으로 RAG 만들면 어떨까라는 잡생각을 조금 했다&lt;/p&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;처음엔 남 생각 말고 나를 생각하며 글을 쓰자
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;만족스럽지 않아도 타인 시선을 의식하며 검열하지 말고 할 수 있는 만큼만 작성해서 올리면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 말이 많이 공감되었다. 블로그의 가장 큰 장점은 언제든 수정이 가능하고, 언제든 업로드가 가능하다는 것이니 할 수 있는 만큼만 먼저 작성하자.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Part 2. 꾸준함, 지속 가능함을 어떻게 만드는가&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;계속 시도하는 것의 중요성&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;저항을 줄이는 환경 : 매주 같은 공간에서 같은 시간에 글쓰기&lt;/li&gt;
&lt;li&gt;함께 하는 사람들 만들기 : 사회적 평판&lt;/li&gt;
&lt;li&gt;하루 일기로 시작하기
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;오늘 해결한 버그? 새롭게 알게 된 사실? 동료에게 설명해 준 내용? 마음가짐 및 오늘의 에너지 상태 등&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ol&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;Lv1. 단순 책, 강의 정리&lt;/li&gt;
&lt;li&gt;Lv2. 특정 기술 사용법 - 목차를 항상 작성하자!&lt;/li&gt;
&lt;li&gt;Lv3. 경험 기반 문제 해결&lt;/li&gt;
&lt;li&gt;Lv4. 생각의 구조화, 통찰 제시&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;결국 핵심은 한 번에 좋은 글을 뽑아내기보다 꾸준히 계속 쓰면서 시간이 지나며 차차 실력이 쌓여 좋은 글도 빠르게 뽑아내는 것이라 느꼈다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;사람에 대한 궁금증&lt;/b&gt;이 생기는 글이 많으면 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Part 3. 글쓰기 시스템 구조화 / 최적화&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;글쓰기에 개발 방법론의 적용&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TDD : 독자 Test case 정의하고 글쓰기
&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;DDD : 글의 도메인, 본질을 정의하기
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;구체적인 기술을 먼저 선정하고, 문제 정의 &amp;rarr; 핵심 원리 &amp;rarr; 구체적 실행 방안으로 정리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모놀리식과 마이크로서비스 아키텍처
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모놀리식 : 처음부터 끝까지 알려주기. 하나의 글에 다 정리되어 공유하기는 좋지만 시간과 노력이 많이 들어간다.&lt;/li&gt;
&lt;li&gt;MSA : 하나의 글에 하나의 주제만 다루는 글
&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;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 방법론의 접목이라는 신선함에 더해 글쓰기를 구조화하니 머리에 더 잘 들어오는 느낌이었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;AI를 활용해서 글도 리뷰하자&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;요즘 AI를 활용해서 검색하고 자료를 찾게 되다 보니 &lt;br /&gt;스스로 곱씹으며 생각 정리할 시간이 없어지고, 인내심도 줄어든 것 같다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt; 글을 쓰면서 생각을 정리하는 시간을 의식적으로 가지도록 노력해야겠다. &lt;/span&gt;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 게임 서버는 어떻게 만들고, 무엇을 만들까? - 최흥배&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;옛날에는 C++ 기반의 서버가 많았지만, 지금은 Go, JS, Rust, Java 등 다양한 언어로도 개발되는 중이다. &lt;br /&gt;실시간 Socket 방식 외에도 모바일 게임으로 주류가 넘어가면서 웹서버와 같은 API 기반 게임 서버도 생겨났으며, LB나 Redis를 붙여서 만든다. DB는 거의 MySQL 기반이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래픽 리소스를 함께 관리해야 하는데 Git은 바이너리 파일 관리가 매우 별로여서 Subversion을 사용하는 경우가 많다는 것이 신기했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 Git으로 exe 바이너리 파일 관리하려다 .git 폴더 용량이 매우 커지는 문제를 경험했고, 그 이후로 GitHub action에 빌드 트리거를 걸어두고 코드만 Git에 넣어두고 .exe 빌드 파일은 GitHub Release로 관리하도록 변경한 경험이 있었는데, 그래픽 같은 큰 바이너리 버전관리 하려면 정말 어렵겠다는 생각이 들었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;5. 바이브코딩 시대에 살아남는 개발자가 되는 방법 - 장영하(마이)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 대체될 사람은 AI를 사용하지 않거나, 활용하지 못하거나, 자동화하지 못하는 사람일 것이다. &lt;br /&gt;키워야 할 역량은 효율성, 설계력이다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;AI 시대를 맞이해 전체 아키텍처를 보는 능력이 더욱 중요해졌으며, (AI가 짜준) 세부적인 모듈을 큰 그림에 맞게 잘 연결할 수 있는 사람이 되어야 경쟁력을 가질 것이라 느꼈다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;6. 평범한 학생인 내가, AI로 6주 만에 글로벌 수상자가 된 전략 - 이지민&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주제 선정이 80% 이상이다. &lt;br /&gt;0부터 만들지 말고, 1부터 시작하기 - 기존 좋은 앱 분석해서 UI / UX 적용하기 &lt;br /&gt;AI를 잘 활용하기 위해선 기본기가 중요하다. &lt;br /&gt;디테일 하나까지 신경 쓰기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GDGoC에서 같이 활동했었는데 정말 대단한 친구다. 이렇게까지 디테일을 챙긴 것을 보고 &lt;s&gt;이미 평범한 학생도 아니었을뿐더러&lt;/s&gt; 수상할 수밖에 없었겠다는 생각이 들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;흔하지 않은 주제 선정, 특히 이슈가 된 현실의 문제를 가져와서 AI를 접목해 잘 해결하는 주제. 이런 것을 도대체 어떻게 떠올리고 찾는지 신기하다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;AI로 프로토타입 제작 &amp;rarr; PoC &amp;rarr; 피봇팅의 사이클을 저비용으로 매우 빠르게 돌릴 수 있게 된 현시점.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;중요한 것은 개발 완성도가 아니라 아이디어와 실행력이지 않나 싶다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>대외활동/강연, 세미나</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/29</guid>
      <comments>https://turtle-hwan.tistory.com/entry/Google-IO-Extended-Incheon-2025-%ED%9B%84%EA%B8%B0#entry29comment</comments>
      <pubDate>Mon, 15 Sep 2025 00:07:07 +0900</pubDate>
    </item>
    <item>
      <title>CORS 해결 후에도 Set-Cookie 인증 인가 처리 안 될 때 해결 방안들</title>
      <link>https://turtle-hwan.tistory.com/entry/CORS-%ED%95%B4%EA%B2%B0-%ED%9B%84%EC%97%90%EB%8F%84-Set-Cookie-%EC%9D%B8%EC%A6%9D-%EC%9D%B8%EA%B0%80-%EC%B2%98%EB%A6%AC-%EC%95%88-%EB%90%A0-%EB%95%8C-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EC%95%88%EB%93%A4</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmCl1e/btsMi0rS0Fi/0PB0AgNNYPqm9Q9lP59Sb0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmCl1e/btsMi0rS0Fi/0PB0AgNNYPqm9Q9lP59Sb0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmCl1e/btsMi0rS0Fi/0PB0AgNNYPqm9Q9lP59Sb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmCl1e%2FbtsMi0rS0Fi%2F0PB0AgNNYPqm9Q9lP59Sb0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;300&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;문제 상황&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;CORS를 해결한 이후에도 Set-Cookie 방식으로 프론트와 백이 로그인 등의 인증 인가 처리를 할 때 오류가 나는 경우이다.&lt;br /&gt;Vite에서 Proxy 설정으로 CORS를 해결하는 방법은 아래 링크에 작성하였다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://turtle-hwan.tistory.com/entry/Vite-Proxy-with-Base-URL-CORS-%ED%95%B4%EA%B2%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://turtle-hwan.tistory.com/entry/Vite-Proxy-with-Base-URL-CORS-%ED%95%B4%EA%B2%B0&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1739971596609&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;Vite Proxy&amp;nbsp;with Base URL &amp;amp; CORS 해결&quot; data-og-description=&quot;Vite에서 proxy를 쓰는데 github page 배포와 같이 base url이 필수적인 세팅에서는 어떻게 proxy 경로 구성해야 하는지 설명 찾기가 힘들어서 이번 기회에 글로 남겨놓으려 한다.배포 환경에서도 proxy를 &quot; data-og-host=&quot;turtle-hwan.tistory.com&quot; data-og-source-url=&quot;https://turtle-hwan.tistory.com/entry/Vite-Proxy-with-Base-URL-CORS-%ED%95%B4%EA%B2%B0&quot; data-og-url=&quot;https://turtle-hwan.tistory.com/entry/Vite-Proxy-with-Base-URL-CORS-%ED%95%B4%EA%B2%B0&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/hYQeb/hyYjvTM0Tv/qeqaZ0GoNG5lpwelkIBvZ1/img.png?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/BRwcl/hyYfBOTd4P/Lx1BK0eknvD3JkPVlkenck/img.png?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/3n87I/hyYfFDIvTr/4EzLdTpbYy9XqprZakr3U0/img.png?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460&quot;&gt;&lt;a href=&quot;https://turtle-hwan.tistory.com/entry/Vite-Proxy-with-Base-URL-CORS-%ED%95%B4%EA%B2%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://turtle-hwan.tistory.com/entry/Vite-Proxy-with-Base-URL-CORS-%ED%95%B4%EA%B2%B0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/hYQeb/hyYjvTM0Tv/qeqaZ0GoNG5lpwelkIBvZ1/img.png?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/BRwcl/hyYfBOTd4P/Lx1BK0eknvD3JkPVlkenck/img.png?width=800&amp;amp;height=600&amp;amp;face=0_0_800_600,https://scrap.kakaocdn.net/dn/3n87I/hyYfFDIvTr/4EzLdTpbYy9XqprZakr3U0/img.png?width=460&amp;amp;height=460&amp;amp;face=0_0_460_460');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Vite Proxy&amp;nbsp;with Base URL &amp;amp; CORS 해결&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Vite에서 proxy를 쓰는데 github page 배포와 같이 base url이 필수적인 세팅에서는 어떻게 proxy 경로 구성해야 하는지 설명 찾기가 힘들어서 이번 기회에 글로 남겨놓으려 한다.배포 환경에서도 proxy를&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;turtle-hwan.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서로 다른 도메인(cross-origin)을 가진 서버와 프론트
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;질문에서는 EC2로 배포된 서버와 S3로 배포된 정적 프론트&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;cross domain 요청이라 서버에서 response cookie를 생성해서 set-cookie로 보내줄 때 secure: true; sameSite: none 으로 설정하고 https가 활성화 되어야 한다고 하던데, 이 방법 뿐인가요?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배포된 환경에서 쿠키를 이용하려면 서버는 공인된 인증서를 발급받아 https를 활성화 시키고, 프론트는 CloudFront를 이용하여 https를 적용시키는 방법밖에 없나요?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;브라우저에 refreshToken이라는 이름의 쿠키는 잘 저장이 되어있는데, 프론트로부터 요청이 올 때 include Credentials이 되어있음에도 불구하고 @CookieValue(value = &quot;refreshToken&quot;)이 null로 옵니다.&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;1554&quot; data-origin-height=&quot;690&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lKGbj/btsMi06sDCb/ktWhdvhWmpWYa1ZE5AFVw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lKGbj/btsMi06sDCb/ktWhdvhWmpWYa1ZE5AFVw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lKGbj/btsMi06sDCb/ktWhdvhWmpWYa1ZE5AFVw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlKGbj%2FbtsMi06sDCb%2FktWhdvhWmpWYa1ZE5AFVw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;690&quot; data-origin-width=&quot;1554&quot; data-origin-height=&quot;690&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-style=&quot;style7&quot; data-ke-type=&quot;horizontalRule&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동아리 프로젝트 진행하다가 받은 질문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에 프로젝트 할 때에도 똑같은 경험을 했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분명 CORS를 해결해서 더 이상 CORS는 안 뜨는데 set-cookie로 인증 인가 처리를 하려니까 안되는 경우다. 이전에는 자세한 원인 파악까지는 못했었고, 이리저리 하다가 프론트 백 모두 https로 올리니까 해결됐었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 이후 얼마 전에 마침 KUIT 해커톤 할 때에도 똑같은 문제가 발생한 팀이 생겨 열심히 붙잡고 이것저것 해결을 시도한 적이 있다. 이번 기회에 이렇게 파고들면서 원인 분석이 명확히 되어 글로 정리해보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전에는 이해를 못하고 해결도 힘들었던 것이 이번에는 차근차근 풀려나가는 것을 보고 실력이 좀 늘었구나 느꼈다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h1&gt;원인 분석 및 설명&lt;/h1&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;set-cookie를 서버에서 줄 때 도메인이 다르다면 SameSite: none으로 설정해야 합니다.&lt;/li&gt;
&lt;li&gt;그런데 SameSite: none인 요청은 브라우저에서 Secure: true가 아니면 거부합니다.&lt;/li&gt;
&lt;li&gt;그런데 Secure: true로 백엔드에서 온 응답에 대한 쿠키를 저장하려면 프론트가 https 인 상태여야 합니다.&lt;/li&gt;
&lt;li&gt;여기까지면 백엔드에서 요청을 받아서 프론트에 쿠키가 잘 저장됩니다.&lt;/li&gt;
&lt;li&gt;그런데 이 쿠키를 fetch credentials include 로 백엔드에 보내려면, 백엔드 배포 주소도 https여야 보내집니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 사진에서 Secure 옆에 느낌표가 있는데, 여기 마우스를 대 보시면 아마 브라우저에서 무슨무슨 조건 때문에 쿠키가 실제로 저장되지 않았다~ 이렇게 뜰 거에요 &amp;rarr; 아마 3번 조건 같습니다&lt;/li&gt;
&lt;li&gt;결론적으론 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;둘 다 https&lt;/b&gt;&lt;/span&gt;여야 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;cross-origin(cross-domain)&lt;/b&gt;&lt;/span&gt;에서 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;set-cookie + httpOnly 방식&lt;/b&gt;&lt;/span&gt;으로 인증-인가 처리를 해줄 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h1&gt;해결 방안&lt;/h1&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;u&gt;둘 다 https로 만들기&lt;/u&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;서버는 한국.도메인 등에서 무료 도메인 받아서 ssl 인증 받기&lt;/li&gt;
&lt;li&gt;프론트는 s3, vercel, github io 등 무료 https 배포 사이트 이용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;u&gt;cross-domain이 아닌, 동일한 domain 사용하기&lt;/u&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;같은 EC2에 같이 배포하기&lt;/li&gt;
&lt;li&gt;프론트 단에서 proxy 사용하기&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;u&gt;set-cookie + httpOnly 방식 대신 header나 body에 token을 넣어서 프론트에 전달&lt;/u&gt;해주고, 프론트에서 cookie나 storage에 저장해서 사용하기&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>프로그래밍/Frontend (React, Javascript, Typescript)</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/28</guid>
      <comments>https://turtle-hwan.tistory.com/entry/CORS-%ED%95%B4%EA%B2%B0-%ED%9B%84%EC%97%90%EB%8F%84-Set-Cookie-%EC%9D%B8%EC%A6%9D-%EC%9D%B8%EA%B0%80-%EC%B2%98%EB%A6%AC-%EC%95%88-%EB%90%A0-%EB%95%8C-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EC%95%88%EB%93%A4#entry28comment</comments>
      <pubDate>Fri, 14 Feb 2025 02:26:07 +0900</pubDate>
    </item>
    <item>
      <title>전역 상태(zustand)에서 배열 concat의 side effect, 해결 방안 (feat. React Strict Mode)</title>
      <link>https://turtle-hwan.tistory.com/entry/React-strict-mode%EB%A1%9C-%ED%83%90%EC%A7%80%EB%90%9C-%EC%A0%84%EC%97%AD-%EC%83%81%ED%83%9Czustand%EC%97%90%EC%84%9C-%EB%B0%B0%EC%97%B4-concat%EC%9D%98-side-effect-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EC%95%88</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nLZ2G/btsLigj4rVl/dtAb7ikUcuVLGWuo4D0khK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nLZ2G/btsLigj4rVl/dtAb7ikUcuVLGWuo4D0khK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nLZ2G/btsLigj4rVl/dtAb7ikUcuVLGWuo4D0khK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnLZ2G%2FbtsLigj4rVl%2FdtAb7ikUcuVLGWuo4D0khK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;300&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;문제 상황&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공공데이터 API에서 받은 하루 동안의 특정 경로의 고속버스 운행 리스트 데이터를 전역 상태인 useTowardBusListStore()에 Array concat으로 기존 배열 데이터 + 받은 데이터를 저장하고 있었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;zustand로 전역 store를 만들었으며, 아래에서 useForwardBusListStore의 concat 함수 코드만 보면 된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;concat 함수를 보면 원래 state list에 새로 들어온 list를 합치는 작업을 한다.&lt;/li&gt;
&lt;li id=&quot;code_1734245424883&quot; class=&quot;javascript&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;forwardBusList: [...state.forwardBusList, ...newforwardBusList]&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1734245266665&quot; class=&quot;pf&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;typescript&quot;&gt;&lt;code&gt;import { create } from 'zustand';
import type { ForwardBusListState } from './index.types';

const initialState = {
  forwardBusList: [],
};

const useForwardBusListStore = create&amp;lt;ForwardBusListState&amp;gt;((set) =&amp;gt; ({
  ...initialState,
  reset: () =&amp;gt; set({ ...initialState }),
  concat: (newforwardBusList) =&amp;gt;
    set((state) =&amp;gt; ({
      ...state,
      forwardBusList: [...state.forwardBusList, ...newforwardBusList],
    })),
  deleteByStartId: (targetStartId) =&amp;gt;
    set((state) =&amp;gt; ({
      ...state,
      forwardBusList: state.forwardBusList.filter(
        (forwardBus) =&amp;gt; forwardBus.startId !== targetStartId
      ),
    })),
}));

export default useForwardBusListStore;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;아래 코드는 의존성 배열이 빈 useEffect()를 사용해 페이지가 처음 렌더링 될 때, 공공데이터 API에서 받아온 정보를 useForwardBusListStore의 concat()을 호출해서 전역 상태에 넣고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1734245321764&quot; class=&quot;typescript&quot; data-ke-language=&quot;typescript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  useEffect(() =&amp;gt; {
    getBusTicketsAPI(
      searchQuery.startId || 'NAEK032',
      searchQuery.destId || 'NAEK300',
      convertYYYYMMDD(searchQuery.startDate)
    )
      .then((data) =&amp;gt; {
        concat(
          convertBusTicketsToBusList(data.response.body.items.item, searchQuery)
        );
      })
  }, []);&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;style1&quot; /&gt;
&lt;h1&gt;의문 사항 및 문제 정의&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Q0. 이 때 어떤 문제가 발생할까?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A0. React Strict Mode로 인해 &lt;b&gt;useEffect가 두 번 실행되는데, concat이 두 번 되어 배열에 동일 정보가 두 번 저장되는 문제가 발생한다!!!!&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;즉, &lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;React Strict Mode로 우리는 전역 상태 관리 함수에서 side effect가 발생한다는 것&lt;/span&gt;&lt;/b&gt;을 알 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Q1. 어떻게 side effect를 없앨 수 있을까?&lt;/li&gt;
&lt;li&gt;Q2. 그렇다면 이게 왜 side effect로 간주되는 걸까?&lt;/li&gt;
&lt;li&gt;Q3. side effect를 없앴을 때 성능 이슈는 없을까?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;side effect가 어디서 발생하는지 알았으니 자연스럽게 이를 어떻게 해결할지 궁금해졌고, 이 의문들에 대해 &lt;a href=&quot;https://github.com/algoORgoal&quot;&gt;실력 좋은 친구&lt;/a&gt;와 이야기하면서 더 깊게 이해할 수 있었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;해결 방안&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Q1. 어떻게 side effect를 없앨 수 있을까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A1. 먼저 어떻게 side effect를 없앨 수 있을지 이야기해보았다. &lt;s&gt;물론 StrictMode를 주석처리한다는 선택지도 있겠지만 말이다.&lt;/s&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A1-1. 처음 떠오르는 생각은 원래 있던 배열 내용 뒤에 concat으로 이어붙이는 것이 아니라, &lt;u&gt;원래 있던 배열을 제거하고 대신 새로운 배열을 넣는 방법&lt;/u&gt;이었다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 방법은 지금 사례와 같이 API에서 받아오는 배열 길이가 작아서 백에서 항상 한 번에 받아올 수 있는 경우에는 효과적이다.&lt;/li&gt;
&lt;li&gt;그런데 만약 무한 스크롤이나 pagenation 때문에 백엔드에서 일정량 단위로 정보를 잘라서 받아와야 한다면 어떨까?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그러면 결국 이를 전역 상태에 저장하기 위해선 &lt;u&gt;이전에 받아온 페이지들의 정보도 제거되면 안 되고 전역 상태에 유지&lt;/u&gt;되어야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A1-2. 이 문제를 해결하기 위해선 &lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;기존 상태를 탐색하고 필터링해서 존재하지 않는 것만 추가&lt;/span&gt;&lt;/b&gt;하면 된다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존 상태에 존재하면 추가하지 않고, 존재하지 않으면 추가하는 방식은 우리의 의도와도 맞아떨어지면서 side effect도 발생하지 않는다.&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-ke-size=&quot;size26&quot;&gt;Q2. 그렇다면 이게 왜 side effect로 간주되는 걸까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A2. 그런데 왜 배열을 단순히 concat 하는 것이 side effect를 발생시키는지 의문이 들었다. 지금 사례에서는 그다지 부작용이 일어나 보이지 않아서 뭔가뭔가 다른 사례를 생각해 보기로 했다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사례1) 만약 API를 호출하는데 응답이 지연되어 재호출을 시도했으나 지연된 응답과 재호출 응답이 두 번 도달하여 각각 전역 상태를 변경한 경우&lt;/li&gt;
&lt;li&gt;사례2) 전역 상태 store 변경 함수가 여러 컴포넌트에서 호출될 가능성이 있고, 동시에 호출되어 전역 상태를 변경한 경우&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;위 두 사례 모두 다 중복 필터링 검증을 하지 않으면&lt;b&gt; 전역 상태에 중복 값이 저장&lt;/b&gt;된다!!!&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A2-1. 게다가 순수 함수의 정의가 동일 입력에 대한 동일 출력이므로, 애초에 단순 concat 결과를 넣어 반환하는 함수는 순수 함수가 아니었던 것이다!!!!
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;concat 자체는 원본 배열을 변경하지 않고 새로운 배열을 반환하므로 순수 함수이다!&lt;/li&gt;
&lt;li&gt;그러나 원본 상태에 concat 한 배열을 다시 저장하여 반환하면 &lt;b&gt;동일한 배열 입력을 계속 반복해서 주었을 때 return 값은 계속 달라지게 되므로 순수하지 못하다.&lt;/b&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;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Q3. side effect를 없앴을 때 성능 이슈는 없을까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A3. 그런데 중복 필터링 검증을 하면 안 할 때에 비해 탐색을 다 돌려야해서 성능 이슈가 생길 것 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 길이 n의 배열이 있고, 새로 추가될 배열이 m이라 하면 단순하게만 봐도 O(nm)의 시간이 걸린다.&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열이 아니라 객체로 저장하거나 id 기반 정규화가 필요하다. hashing을 해놓는 것도 좋을 수 있다.&lt;/li&gt;
&lt;li&gt;id 기반 정규화를 프론트에서 진행해도 되지만 배열을 객체로 바꾸는 시간이 너무 길다면 백에서 정규화된 데이터를 받아오는 게 나을 수 있을 것이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그런데 state는 상태 불변성을 위해 항상 새로운 객체를 만든다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이 때문에 immutable.js 를 도입해 상태 불변성을 유지하면서 시간복잡도를 줄여야 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;요약 정리&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Q0. 이 때 어떤 문제가 발생할까?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A0. React Strict Mode로 인해 useEffect가 두 번 실행되는데, concat이 두 번 되어 배열에 동일 정보가 두 번 저장되는 문제가 발생한다!!!!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Q1. 어떻게 side effect를 없앨 수 있을까?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A1-1. 원래 배열을 제거하고 새로 만들어 넣는다.&lt;/li&gt;
&lt;li&gt;A1-2. 무한 스크롤이나 pagenation 같은 경우, 기존 상태를 필터링해서 존재하지 않는 것만 추가한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Q2. 그렇다면 이게 왜 side effect로 간주되는 걸까?
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;A2. concat은 순수함수지만 원본 배열에 다시 concat한 배열을 넣어 반환하면 순수하지 못하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Q3. side effect를 없앴을 때 성능 이슈는 없을까?
&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;만약 많은 정보를 프론트에도 저장할 필요성이 있다면, id 기반 정규화를 하거나 immutable.js를 사용해서 상태 불변성을 유지하면서 시간 복잡도를 줄여야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>프로그래밍/Frontend (React, Javascript, Typescript)</category>
      <category>array concat</category>
      <category>react</category>
      <category>Side Effect</category>
      <category>strict mode</category>
      <category>zustand</category>
      <category>전역 상태 관리</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/27</guid>
      <comments>https://turtle-hwan.tistory.com/entry/React-strict-mode%EB%A1%9C-%ED%83%90%EC%A7%80%EB%90%9C-%EC%A0%84%EC%97%AD-%EC%83%81%ED%83%9Czustand%EC%97%90%EC%84%9C-%EB%B0%B0%EC%97%B4-concat%EC%9D%98-side-effect-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EC%95%88#entry27comment</comments>
      <pubDate>Sun, 15 Dec 2024 16:03:59 +0900</pubDate>
    </item>
    <item>
      <title>Vite Proxy Base URL 포함한 설정으로 CORS 해결하기!!</title>
      <link>https://turtle-hwan.tistory.com/entry/Vite-Proxy-with-Base-URL-CORS-%ED%95%B4%EA%B2%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Vite에서 proxy를 쓰는데 github page 배포와 같이 base url이 필수적인 세팅에서는 어떻게 proxy 경로 구성해야 하는지 설명 찾기가 힘들어서 이번 기회에 글로 남겨놓으려 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배포 환경에서도 proxy를 이용하고 싶었는데 github page에서는 지원하지 않는 것인지 실패했고, vercel의 경우 vercel.json을 통한 추가 경로 설정으로 성공했다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(참고 : &lt;a href=&quot;https://velog.io/@jeajea0127/Vercel에서-proxy-설정하기&quot;&gt;https://velog.io/@jeajea0127/Vercel에서-proxy-설정하기&lt;/a&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;netlify에서도 비슷한 추가 설정으로 가능한 것 같다 : &lt;a href=&quot;https://github.com/vitejs/vite/discussions/17381#discussioncomment-9939768&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/vitejs/vite/discussions/17381#discussioncomment-9939768&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;github page는 정적 페이지 배포만 지원해서 불가능한 것 같다.. : &lt;a href=&quot;https://github.com/vitejs/vite/discussions/15523&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/vitejs/vite/discussions/15523&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CORS를 프론트 단에서 해결 가능한 proxy 기능에 대한 전반적인 설명도 덧붙인다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biNeYK/btsKY3rJYnC/pJzVSLFBEdESnM8GO8qno0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biNeYK/btsKY3rJYnC/pJzVSLFBEdESnM8GO8qno0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biNeYK/btsKY3rJYnC/pJzVSLFBEdESnM8GO8qno0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiNeYK%2FbtsKY3rJYnC%2FpJzVSLFBEdESnM8GO8qno0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;300&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h1&gt;Proxy란?&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프록시는 기존 클라이언트와 서버 사이에서 데이터나 HTTP 요청을 중계하는 역할을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 proxy가 뭔지 엄청 헷갈렸는데, 지금 보니 단순히 클라이언트 &amp;rarr; 서버로 요청을 보낼 때 중간에서 중계하는 역할이 끼어 있으면 이 역할을 하는 친구들을 전부 통틀어서 proxy라 부르는 것으로 이해했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트가 요청을 보낼 때 해당 요청을 먼저 받아 검증할 수도 있고, 서버에서 받은 응답을 캐싱하거나 보안 처리를 추가로 할 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트 측에 있는지, 서버 측에 있는지에 따라 포워드 프록시, 리버스 프록시로 구분된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;포워드 프록시 (Forward Proxy)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클라이언트의 요청을 받아 외부 서버로 중계한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회사나 학교 등 단체에서 특정 공인 IP 아래 여러 서브넷을 두고 여기서 오는 요청들을 한 번에 모아 검증한 후 외부 인터넷에 연결할 때 사용 가능하다. 같은 사이트에 대한 중복 요청은 응답을 캐싱해두었다 주는 방식으로 효율을 높일 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프록시 서버를 별도로 두고 요청을 프록시 서버를 거쳐서 가게 하는 방식으로 원래 IP 주소를 숨길 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vite Proxy 처럼 CORS 오류를 프론트 단에서 해결하는 방법으로도 쓴다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리버스 프록시 (Reverse Proxy)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버 측에서 동작하며 클라이언트 요청들을 먼저 받아 백엔드 서버로 전송한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정 IP나 특정 포트로 오는 요청을 미리 거르는 보안 처리를 할 수도 있고, 갑자기 많이 들어오는 요청에 대해 트래픽 분산, 로드밸런싱을 해줄 수도 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h1&gt;Vite에서 제공하는 Proxy 기능&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그렇다면 Vite에서는 어떻게 Proxy를 제공하는가?&lt;/li&gt;
&lt;li&gt;그리고 이 Proxy를 통해 어떻게 CORS를 해결하는가?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 부딪힌 문제 상황은 다음과 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공공데이터 포탈에서 제공하는 API로 데이터를 프론트에서 바로 받아오고 싶은데, 당연히 공공데이터 포탈 측 서버의 Allow-origin에는 우리 프론트 서버가 등록되어 있지도 않으니 CORS 오류가 나는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통의 프로젝트에서는 브라우저 CORS 정책 제한이 없는 백엔드 서버에서 공공데이터 정보를 받아서 정제 후 프론트에 던져줘서 잘 발생하지 않는 문제다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;하지만 수업 플젝이라 백엔드 없이 가기로 했기 때문에.. 그냥 Mock Data 쓸 걸.. 왜 실제 데이터 받아오려다&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 문제를 Vite Proxy를 통해 해결할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원리를 요약하면 결국 브라우저에서 CORS를 거는 게 문제이므로, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;Vite에서 브라우저를 거치지 않고 바로 원하는 API 서버 주소와 우리 프론트의 특정 주소를 매핑시켜주는 것&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 겉에서 보기에 &lt;u&gt;우리 브라우저는 orgin이 같은 자신의 프론트 주소로 request를 날리는 것으로 인식하고 CORS를 뿜지 않는다!!&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저 (origin: 내프론트주소) Request &amp;rarr; &lt;a href=&quot;https://xn--220bn9lj7huvh8tm0kd/api&quot;&gt;https://내프론트주소/api&lt;/a&gt; (Vite에서 해당 주소에 백엔드 주소를 매핑시켜서 Response를 받아온다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 원리를 설명한 글도 못 찾고 proxy에 대한 이해도 부족한 처음엔 왜 이렇게 작동하는지 알기 힘들었다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Vite 공식문서 예시&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;vite.config.ts 파일&lt;/blockquote&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;export default defineConfig({
  server: {
    proxy: {
      // 문자열만:  -&amp;gt; 
      '/foo': '',
      // 옵션과 함께: http://localhost:5173/api/bar-&amp;gt; &amp;lt;http://jsonplaceholder.typicode.com/bar&amp;gt;
      '/api': {
        target: '&amp;lt;http://jsonplaceholder.typicode.com&amp;gt;',
        changeOrigin: true,
        rewrite: (path) =&amp;gt; path.replace(/^\\/api/, '')
      },
      // 정규식(RegExp)과 함께:  -&amp;gt; &amp;lt;http://jsonplaceholder.typicode.com/&amp;gt;
      '^/fallback/.*': {
        target: '&amp;lt;http://jsonplaceholder.typicode.com&amp;gt;',
        changeOrigin: true,
        rewrite: (path) =&amp;gt; path.replace(/^\\/fallback/, '')
      },
      // 프락시 인스턴스 사용
      '/api': {
        target: '&amp;lt;http://jsonplaceholder.typicode.com&amp;gt;',
        changeOrigin: true,
        configure: (proxy, options) =&amp;gt; {
          // proxy 변수에는 'http-proxy'의 인스턴스가 전달됩니다
        }
      },
      // 웹소켓 또는 socket.io 프락시: ws://localhost:5173/socket.io -&amp;gt; ws://localhost:5174/socket.io
      // `rewriteWsOrigin`을 사용할 때는 주의하세요. CSRF 공격에 노출될 수 있습니다.
      '/socket.io': {
        target: 'ws://localhost:5174',
        ws: true,
        rewriteWsOrigin: true,
      }
    }
  }
})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 문서에서 위와 같은 예시를 줬는데, /api 를 붙이는 첫 예시를 보면 &lt;a href=&quot;http://localhost:5173/api%EC%9D%98&quot;&gt;http://localhost:5173/api&lt;/a&gt; 로 오는 모든 요청을 target 주소로 매핑시키겠다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 rewrite 옵션이 없으면 &lt;a href=&quot;http://jsonplaceholder.typicode.com/api&quot;&gt;http://jsonplaceholder.typicode.com/api&lt;/a&gt; 로 요청이 가겠지만, /api는 우리가 프론트에서 경로를 구분하려 임의로 준 것이므로 rewrite에서 /api 경로만 제거해줘 실제 요청에선 없앤다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;fetch 코드 부분&lt;/blockquote&gt;
&lt;pre class=&quot;javascript&quot;&gt;&lt;code&gt; const response = await fetch(
    `/api/bar?${queryString}`,
    {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
    }
  );
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;proxy 처리된 api를 fetch로 받는 예시는 위와 같다. 프론트 자신 서버의 /api/bar 경로로 요청을 보내는 것과 동일하고, 브라우저에서도 origin은 모두 자기자신으로 뜨지만 Vite에서 백엔드 경로와 매핑시켜주는 것이다!!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;base url이 있을 때 Vite Proxy 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 base url이 존재할 때 VIte Proxy 설정을 어떻게 해야 하느냐는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 문서에도 설명이 없고, 이 문제를 다룬 블로그도 못 찾아서 열심히 열심히 경로 이리저리 다 바꾸면서 실험하면서 알아냈다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;vite.config.ts 파일&lt;/blockquote&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { TanStackRouterVite } from '@tanstack/router-plugin/vite';
import svgr from 'vite-plugin-svgr';

const isTest = process.env.NODE_ENV === 'test';

// &amp;lt;https://vite.dev/config/&amp;gt;
export default defineConfig({
  plugins: [svgr(), !isTest &amp;amp;&amp;amp; TanStackRouterVite(), react()],
  base: '/uxplorers-frontend/',
  server: {
    proxy: {
      '/uxplorers-frontend/api/ExpBusArrInfoService': {
        target: '&amp;lt;http://apis.data.go.kr/1613000&amp;gt;',
        changeOrigin: true,
        rewrite: (path) =&amp;gt; path.replace(/^\\/uxplorers-frontend\\/api/, ''),
      },
      '/uxplorers-frontend/api/ExpBusInfoService': {
        target: '&amp;lt;http://apis.data.go.kr/1613000&amp;gt;',
        changeOrigin: true,
        rewrite: (path) =&amp;gt; path.replace(/^\\/uxplorers-frontend\\/api/, ''),
      },
      // '/uxplorers-frontend/api': {
      //   target: '&amp;lt;http://apis.data.go.kr/1613000&amp;gt;',
      //   changeOrigin: true,
      //   rewrite: (path) =&amp;gt; path.replace(/^\\/api/, ''),
      // },
    },
  },
});&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote style=&quot;color: #666666; text-align: left;&quot; data-ke-style=&quot;style2&quot;&gt;fetch 코드 부분&lt;/blockquote&gt;
&lt;pre class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot;&gt;&lt;code&gt;  const response = await fetch(
    `/uxplorers-frontend/api/ExpBusArrInfoService/getExpBusArrPrdtInfo?${queryString}`,
    {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
    }
  );&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;처음엔 base url을 vite.config.ts에서 설정해주니까 fetch 보낼 때나 proxy 설정할 때 앞에 자동으로 붙여주는게 아닐까 추측했는데, 이게 아니었다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에 자동으로 붙여주지 않으므로, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;직접 base url을 proxy 등록 시, fetch request url 맨 앞에 추가해주어야 한다!!!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 당연히 이는 우리 프론트에서만 사용되는 url route 부분이므로, 실제 요청 보낼 때 제거를 위해 path.replace 구문에도 추가해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &lt;a href=&quot;http://myfrontserver:5173/base-url/api/route&quot;&gt;http://myfrontserver:5173/base-url/api/route&lt;/a&gt; 로 보내는 request를 &lt;a href=&quot;http://target-api-url/route&quot;&gt;http://target-api-url/route&lt;/a&gt; 로 매핑시켜 준다는 것이고, fetch('/base-url/api/route?${queryString}'); 으로 전송해야 한다는 것이다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게다가 vite.config.ts 파일 내에서 환경변수를 불러오려면 import.meta.env가 아닌, process.env를 써야 하는 것 같다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;TODO&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CORS에 대한 블로그 글도 추가로 작성해야겠다..&lt;/li&gt;
&lt;li&gt;github pages 배포에서 proxy 이용 방법도 찾아봐야겠다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고 자료&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://ko.vite.dev/config/server-options&quot;&gt;https://ko.vite.dev/config/server-options&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://yozm.wishket.com/magazine/detail/2565/&quot;&gt;https://yozm.wishket.com/magazine/detail/2565/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>프로그래밍/Frontend (React, Javascript, Typescript)</category>
      <category>Base URL</category>
      <category>proxy</category>
      <category>react</category>
      <category>vite</category>
      <category>vite proxy</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/25</guid>
      <comments>https://turtle-hwan.tistory.com/entry/Vite-Proxy-with-Base-URL-CORS-%ED%95%B4%EA%B2%B0#entry25comment</comments>
      <pubDate>Thu, 28 Nov 2024 16:31:11 +0900</pubDate>
    </item>
    <item>
      <title>10분 만에 웹사이트에 PWA 적용해서 웹앱 만들기!</title>
      <link>https://turtle-hwan.tistory.com/entry/10%EB%B6%84-%EB%A7%8C%EC%97%90-%EA%B8%B0%EC%A1%B4-%EC%9B%B9%EC%82%AC%EC%9D%B4%ED%8A%B8%EC%97%90-PWAProgressive-Web-Apps-%EC%A0%81%EC%9A%A9%ED%95%B4%EC%84%9C-%EC%9B%B9%EC%95%B1%EC%9C%BC%EB%A1%9C-%EB%A7%8C%EB%93%A4%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;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9dINP/btsKKpfCzJs/rVpxz9yZRVTOxA6plHBsw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9dINP/btsKKpfCzJs/rVpxz9yZRVTOxA6plHBsw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9dINP/btsKKpfCzJs/rVpxz9yZRVTOxA6plHBsw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9dINP%2FbtsKKpfCzJs%2FrVpxz9yZRVTOxA6plHBsw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;300&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;사실 처음 붙잡았을 때는 오류 해결하느라 1시간 정도 걸렸고, 글로 정리해서 작성하는 데는 미루다 일주일 넘게 걸렸다... 그래도 manifest.json 등록하는 것은 정말로 금방 할 수 있다!!&lt;/s&gt;&lt;/p&gt;
&lt;h1&gt;PWA란?&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Progressive Web Apps 의 약자로 브라우저 기반의 웹을 앱처럼 바로 설치해서 사용 가능한 기술이다.&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;아직까지 한글 정보는 많이 없고 설명이 적어 MDN 공식 문서가 가장 좋았다. MDN 문서 중에서도 번역되지 않은 부분이 많아 나중에 기여해보면 좋을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/Progressive_web_apps/Tutorials/js13kGames&quot;&gt;https://developer.mozilla.org/ko/docs/Web/Progressive_web_apps/Tutorials/js13kGames&amp;nbsp;&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1731556723153&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그레시브 웹 앱 소개 - 프로그레시브 웹 앱 | MDN&quot; data-og-description=&quot;이 문서는 프로그레시브 웹 앱(PWA)의 소개입니다. PWA가 무엇이고 일반 웹 앱에 어떤 이점을 가져다주는지 설명합니다.&quot; data-og-host=&quot;developer.mozilla.org&quot; data-og-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/Progressive_web_apps/Tutorials/js13kGames&quot; data-og-url=&quot;https://developer.mozilla.org/ko/docs/Web/Progressive_web_apps/Tutorials/js13kGames&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/S1HnH/hyXzRwr7UL/JQIUmarzIiz0lY78F7fS5k/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/Progressive_web_apps/Tutorials/js13kGames&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/Progressive_web_apps/Tutorials/js13kGames&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/S1HnH/hyXzRwr7UL/JQIUmarzIiz0lY78F7fS5k/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그레시브 웹 앱 소개 - 프로그레시브 웹 앱 | MDN&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 문서는 프로그레시브 웹 앱(PWA)의 소개입니다. PWA가 무엇이고 일반 웹 앱에 어떤 이점을 가져다주는지 설명합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.mozilla.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h1&gt;PWA 만들기&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적인 웹을 PWA로 만들기 위해 해주어야 하는 것은 다음 세 가지다. 처음에 manifest.json은 업로드 했는데 index.html에 안 넣어줘서 브라우저에서 PWA 설치 버튼이 뜨지 않아 한참 헤맸다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;manifest.json 생성 및 업로드&amp;nbsp;&lt;br /&gt;보통 사이트의 root 경로에, 사이트url/manifest.json 입력 시 잘 뜨도록 업로드 해주면 된다.&lt;/li&gt;
&lt;li&gt;icon img 등록 (512x512 기준으로 작은 사이즈 1개, 큰 사이즈 최소 1개 이상 필요)&lt;/li&gt;
&lt;li&gt;메인 사이트 index.html 의 &amp;lt;head&amp;gt; 태그에 manifest.json 경로 &amp;lt;link&amp;gt; 추가하기!!!&lt;br /&gt;
&lt;pre id=&quot;code_1731556392354&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;html&quot;&gt;&lt;code&gt;&amp;lt;link rel=&quot;manifest&quot; href=&quot;manifest.json&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;PWA builder 웹사이트 이용해서 manifest.json 쉽게 만들기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pwa builder 웹사이트를 이용하면 보다 쉽게 manifest.json을 작성할 수 있고, 특정 웹사이트에 PWA가 잘 적용되어 있는지, 부족한 점은 무엇인지 자세히 알려준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;image도 하나를 넣으면 자동으로 사이즈별로 만들어서 다운받을 수 있고, manifest.json에 작성까지 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.pwabuilder.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.pwabuilder.com/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1731556546246&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;PWABuilder&quot; data-og-description=&quot;&quot; data-og-host=&quot;www.pwabuilder.com&quot; data-og-source-url=&quot;https://www.pwabuilder.com/&quot; data-og-url=&quot;https://www.pwabuilder.com/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.pwabuilder.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.pwabuilder.com/&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;PWABuilder&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;www.pwabuilder.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #777777; text-align: center;&quot;&gt;manifest.json이 등록이 안 되어 있거나, 업로드는 되어 있어도 index.html에 &amp;lt;link&amp;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;1099&quot; data-origin-height=&quot;813&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k8YS3/btsKJjzLeTF/L8U9oXn5xKeO0qhJMVzFTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k8YS3/btsKJjzLeTF/L8U9oXn5xKeO0qhJMVzFTk/img.png&quot; data-alt=&quot;manifest.json을 인식 못하는 경우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k8YS3/btsKJjzLeTF/L8U9oXn5xKeO0qhJMVzFTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk8YS3%2FbtsKJjzLeTF%2FL8U9oXn5xKeO0qhJMVzFTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1099&quot; height=&quot;813&quot; data-origin-width=&quot;1099&quot; data-origin-height=&quot;813&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;manifest.json을 인식 못하는 경우&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;manifest.json을 잘 인식하면 다음과 같이 뜬다. 추가적으로 넣으면 좋지만 빠져 있는 정보들을 알려준다. Windows, iOS, Android, meta(???) store에 등록할 수 있도록 .apk 등의 파일로도 생성해주는 것 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1108&quot; data-origin-height=&quot;846&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFFQVG/btsKIA9QFQD/VYvNUWaNuuObermztCV9Ek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFFQVG/btsKIA9QFQD/VYvNUWaNuuObermztCV9Ek/img.png&quot; data-alt=&quot;manifest.json을 잘 인식하는 경우&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFFQVG/btsKIA9QFQD/VYvNUWaNuuObermztCV9Ek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFFQVG%2FbtsKIA9QFQD%2FVYvNUWaNuuObermztCV9Ek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1108&quot; height=&quot;846&quot; data-origin-width=&quot;1108&quot; data-origin-height=&quot;846&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;manifest.json을 잘 인식하는 경우&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Vite + github pages 로 배포된 서비스에 PWA 적용하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Vite기반이라 정적 파일인 manifest.json과 img 들은 public 폴더에 넣어주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후 index.html의 &amp;lt;head&amp;gt; 태그 내 &amp;lt;link&amp;gt; 태그에 manifest.json 경로도 등록해주었다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;612&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eelUuS/btsKHMJ1X6R/bDUeZN9XRpFuHvs1iG54X0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eelUuS/btsKHMJ1X6R/bDUeZN9XRpFuHvs1iG54X0/img.png&quot; data-alt=&quot;public 폴더&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eelUuS/btsKHMJ1X6R/bDUeZN9XRpFuHvs1iG54X0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeelUuS%2FbtsKHMJ1X6R%2FbDUeZN9XRpFuHvs1iG54X0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;376&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;612&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;public 폴더&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;manifest.json에 작성하는 color 중 &quot;theme_color&quot;는 앱 내의 주소 창, 위의 남는 부분의 색상이고, &quot;background_color&quot;는 설치되는 앱 아이콘에 공간이 남았을 때 채워지는 색상이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; 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;github page에 배포해서 그런지 start_url 적용에 애먹었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;manifest.json에 start_url을 &quot;/&quot;로 등록했을 때&amp;nbsp; 경로 시작점이 path parameter의 최상단으로 적용되는 것이다!&lt;br /&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;처음에&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;letter-spacing: 0px;&quot; href=&quot;https://kuit-space.github.io/KUIT-Space-front&quot;&gt;https://kuit-space.github.io/KUIT-Space-front&lt;/a&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;경로인데 start_url에 &amp;ldquo;/&amp;rdquo; 을 넣어두었더니&amp;nbsp;&lt;/span&gt;https://kuit-space.github.io/&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp; 경로를 시작 페이지로 보여주어 404 Not Found가 떴다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;여기서 헤맸던 것이 manifest.json은 배포된 경로, 즉 전자의 경로에 등록된&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;a href=&quot;https://kuit-space.github.io/KUIT-Space-front/manifest.json&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://kuit-space.github.io/KUIT-Space-front/manifest.json&lt;/a&gt; 을 가져오는데 왜 start_url은 path 처음부터 가져오는 걸까.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재는 start_url을 &amp;nbsp;&amp;nbsp;&quot;start_url&quot;: &quot;/KUIT-Space-front&quot; 이렇게 넣어서 잘 작동하는 상태이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 또 &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/Manifest/start_url&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;공식문서&lt;/a&gt; 뜯어보면 start_url 경로가 manifest.json이 등록된 곳 기준으로 가져온다고 되어 있는데 잘 모르겠다..&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; 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;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/by1IBz/btsKItQI5zd/4iKO6ibDaFbZUKpaeXz4k1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/by1IBz/btsKItQI5zd/4iKO6ibDaFbZUKpaeXz4k1/img.png&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot; data-is-animation=&quot;false&quot; width=&quot;300&quot; style=&quot;width: 49.4186%; margin-right: 10px;&quot; data-widthpercent=&quot;50&quot; id=&quot;kEditorPhotosEditingImage-3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/by1IBz/btsKItQI5zd/4iKO6ibDaFbZUKpaeXz4k1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fby1IBz%2FbtsKItQI5zd%2F4iKO6ibDaFbZUKpaeXz4k1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;3088&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k9VhB/btsKIuWnepH/BK5cYxVtrTik2mBSrtiKh1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k9VhB/btsKIuWnepH/BK5cYxVtrTik2mBSrtiKh1/img.png&quot; data-origin-width=&quot;1440&quot; data-origin-height=&quot;3088&quot; data-is-animation=&quot;false&quot; width=&quot;300&quot; style=&quot;width: 49.4186%;&quot; data-widthpercent=&quot;50&quot; id=&quot;kEditorPhotosEditingImage-4&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k9VhB/btsKIuWnepH/BK5cYxVtrTik2mBSrtiKh1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk9VhB%2FbtsKIuWnepH%2FBK5cYxVtrTik2mBSrtiKh1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1440&quot; height=&quot;3088&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비록 몇 가지 단점이 있지만 웹 뷰로 감싸지 않아도 푸시알림도 가능하고 거의 네이티브 앱과 흡사하게 사용할 수 있는 건 정말 큰 장점이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;페이지 이동할 때, 특히 카카오 로그인 같이 타 사이트로 리다이렉트 될 때 위에 브라우저처럼 주소 바가 뜬다.&lt;/li&gt;
&lt;li&gt;상단 노치 바가 있는 아이폰의 경우 화면이 밀려서 아래로 약간 내려가고 노치 바에 주소 바가 가려서 뜨는 문제가 있다.&lt;/li&gt;
&lt;li&gt;그리고 설정 파일이 변경되는 거라 당연한 것일 수도 있으나 manifest.json이 변경된다면 앱을 새로 받아야 적용된다.&lt;/li&gt;
&lt;li&gt;웹 기반이라 페이지만 새로 배포된다면 그 즉시 컨텐츠 업데이트가 바로 된다는 장점이 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Service Worker&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Service Worker를 통해 추가적인 다양한 동작을 만들 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&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;a href=&quot;https://developer.mozilla.org/ko/docs/Web/Progressive_web_apps/Tutorials/js13kGames/Offline_Service_workers&quot;&gt;https://developer.mozilla.org/ko/docs/Web/Progressive_web_apps/Tutorials/js13kGames/Offline_Service_workers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DOM에는 접근 불가능&lt;/li&gt;
&lt;li&gt;FCM과 연동해서 사용자 기기에 푸시알림을 띄울 수도 있다!!! &amp;rarr; 정말로 네이티브 앱에 가깝게 사용 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/Service_Worker_API&quot;&gt;https://developer.mozilla.org/ko/docs/Web/API/Service_Worker_API&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1731558653055&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;Service Worker API - Web API | MDN&quot; data-og-description=&quot;서비스 워커는 웹 응용 프로그램, 브라우저, 그리고 (사용 가능한 경우) 네트워크 사이의 프록시 서버 역할을 합니다. 서비스 워커의 개발 의도는 여러가지가 있지만, 그 중에서도 효과적인 오프&quot; data-og-host=&quot;developer.mozilla.org&quot; data-og-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/API/Service_Worker_API&quot; data-og-url=&quot;https://developer.mozilla.org/ko/docs/Web/API/Service_Worker_API&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/iN64W/hyXwnjwPTk/KkQnmrYojfR1S4eAgZVAz0/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/API/Service_Worker_API&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.mozilla.org/ko/docs/Web/API/Service_Worker_API&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/iN64W/hyXwnjwPTk/KkQnmrYojfR1S4eAgZVAz0/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Service Worker API - Web API | MDN&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;서비스 워커는 웹 응용 프로그램, 브라우저, 그리고 (사용 가능한 경우) 네트워크 사이의 프록시 서버 역할을 합니다. 서비스 워커의 개발 의도는 여러가지가 있지만, 그 중에서도 효과적인 오프&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.mozilla.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에 PWA와 FCM을 연동해서 유저 기기에 푸시 알림을 띄우는 것까지 시도할 예정이다.&lt;/p&gt;</description>
      <category>프로그래밍/Frontend (React, Javascript, Typescript)</category>
      <category>MDN</category>
      <category>Progressive Web Apps</category>
      <category>pwa</category>
      <category>웹앱</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/24</guid>
      <comments>https://turtle-hwan.tistory.com/entry/10%EB%B6%84-%EB%A7%8C%EC%97%90-%EA%B8%B0%EC%A1%B4-%EC%9B%B9%EC%82%AC%EC%9D%B4%ED%8A%B8%EC%97%90-PWAProgressive-Web-Apps-%EC%A0%81%EC%9A%A9%ED%95%B4%EC%84%9C-%EC%9B%B9%EC%95%B1%EC%9C%BC%EB%A1%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0#entry24comment</comments>
      <pubDate>Thu, 14 Nov 2024 13:32:05 +0900</pubDate>
    </item>
    <item>
      <title>[우아한테크코스 7기] 프리코스 1주차 회고 - 프론트엔드</title>
      <link>https://turtle-hwan.tistory.com/entry/%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-7%EA%B8%B0-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-1%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1407&quot; data-origin-height=&quot;1706&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/df0hoj/btsKqJlqTGw/xXnfnNMN8Ftn8JWI2SEmKK/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/df0hoj/btsKqJlqTGw/xXnfnNMN8Ftn8JWI2SEmKK/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/df0hoj/btsKqJlqTGw/xXnfnNMN8Ftn8JWI2SEmKK/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdf0hoj%2FbtsKqJlqTGw%2FxXnfnNMN8Ftn8JWI2SEmKK%2Fimg.webp&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;364&quot; data-origin-width=&quot;1407&quot; data-origin-height=&quot;1706&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;프리코스 참가와 1주차&lt;/h1&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;h2 data-ke-size=&quot;size26&quot;&gt;자기소개서 작성&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그래머가 되려는 이유와 지원 동기 2000자&lt;/li&gt;
&lt;li&gt;오랜 시간 몰입했던 경험 그리고 도전 2000자&lt;/li&gt;
&lt;li&gt;프리코스 목표 설정 1000자&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;도합 5000자에 달하는 자소서를 쓰면서 생각보다 글로 녹여내 쓸만한 경험이 많이 없다는 것을 느꼈다. 블로그를 좀 더 열심히 쓰면서 글을 많이 모아두어야겠다.&lt;/p&gt;
&lt;h1&gt;요구사항&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요구사항은 기능 요구사항, 입출력 요구 사항, 프로그래밍 요구 사항으로 나뉘며 이를 모두 만족해야 한다.&lt;/li&gt;
&lt;li&gt;1주차 미션은 &amp;ldquo;입력한 문자열에서 숫자를 추출하여 더하는 계산기&amp;rdquo;이다.
&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;예: &quot;&quot; =&amp;gt; 0, &quot;1,2&quot; =&amp;gt; 3, &quot;1,2,3&quot; =&amp;gt; 6, &quot;1,2:3&quot; =&amp;gt; 6&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;앞의 기본 구분자(쉼표, 콜론) 외에 커스텀 구분자를 지정할 수 있다. 커스텀 구분자는 문자열 앞부분의 &quot;//&quot;와 &quot;\n&quot; 사이에 위치하는 문자를 커스텀 구분자로 사용한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;예를 들어 &quot;//;\n1;2;3&quot;과 같이 값을 입력할 경우 커스텀 구분자는 세미콜론(;)이며, 결과 값은 6이 반환되어야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사용자가 잘못된 값을 입력할 경우 &quot;[ERROR]&quot;로 시작하는 메시지와 함께 Error를 발생시킨 후 애플리케이션은 종료되어야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;입출력 요구 사항은 다음과 같다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;입력 : 구분자와 양수로 구성된 문자열&lt;/li&gt;
&lt;li&gt;출력 : 덧셈 결과&lt;/li&gt;
&lt;li&gt;실행 결과 예시&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;덧셈할 문자열을 입력해 주세요.
1,2:3
결과 : 6
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;설계한 기능 목록&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1주차라 그런지 생각보다 문제가 간단해서 기능 설계도 적게 가능했다. 오히려 리팩토링 할 때 시간이 더 많이 걸렸다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자 입출력&lt;/li&gt;
&lt;li&gt;기본 구분자 (,:) 인식&lt;/li&gt;
&lt;li&gt;커스텀 구분자 인식&lt;/li&gt;
&lt;li&gt;사용자가 잘못된 값을 입력할 경우 예외 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Test Cases 및 예외처리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나중에 다른 사람들을 보니 소수점 예외 처리와 정수형 오버플로우 예외 처리까지 고려해서 해준 사람들이 있었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;음수 예외&lt;/li&gt;
&lt;li&gt;문자 예외&lt;/li&gt;
&lt;li&gt;기본 구분자 사용&lt;/li&gt;
&lt;li&gt;빈 문자열 0 출력 확인&lt;/li&gt;
&lt;li&gt;커스텀 구분자 사용&lt;/li&gt;
&lt;li&gt;커스텀 구분자 사용 여러 문자&lt;/li&gt;
&lt;li&gt;커스텀 구분자 사용 공백&lt;/li&gt;
&lt;li&gt;커스텀 구분자가 숫자인 예외&lt;/li&gt;
&lt;li&gt;커스텀 구분자 없는 예외&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;리팩토링&lt;/h1&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;class App {
  async run() {
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 class를 주고, run()을 작동시키면 기본적인 동작을 하도록 구성되어 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에 함수로 분리할 생각을 안하고 일단 기능을 다 담아서 짜보자는 생각으로 짰더니 나중에 분리하기가 더 힘들었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;run() 안에서 여러 일을 하던 것을 메서드로 분리&lt;/li&gt;
&lt;li&gt;stringSplitSumCalc(string, customSeparator)
&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;커스텀 구분자가 없으면 customSeparator 인자에 null이 들어오게 된다. 다시 보면 null일수도 있다는 사실이 명시적으로 드러나지 않는 것 같아 개선이 필요할지 고민된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;throw new Error 하는 부분을 validateNumber() , validateSeparator() 메서드로 분리&lt;/li&gt;
&lt;li&gt;hasCustomSeparator() 메서드 분리&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;새로 알게 된 것&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;node.js 버전이 맞지 않아 업데이트 해야 했었다. window에선 node.js를 아예 새로 설치하거나, nvm을 통해 node 버전 관리하는 방법이 있었는데 nvm 버전 관리가 더 간편해서 이를 이용했다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;참고링크 : &lt;a href=&quot;https://cheoltecho.tistory.com/15&quot;&gt;https://cheoltecho.tistory.com/15&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;split() 함수 안에서 /[,:]/와 /[,:]/g 두 정규표현식을 사용했을 때 결과가 같은 이유
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;split() 함수 자체가 문자열을 &amp;ldquo;전부 탐색&amp;rdquo;하여 &amp;ldquo;분리&amp;rdquo;하는 작업을 하기 때문에 정규표현식 g 플래그가 없어도 split()에서 전체 문자열을 탐색해준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;JavaScript에서 숫자인지 판단하는 방법
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;isNaN() 사용 : true, false, 문자열 등도 숫자로 암시적 형변환 후 검사하기 때문에 숫자라고 판단될 수 있다. 한 번 더 조건문을 세워 걸러주어야 한다.&lt;/li&gt;
&lt;li&gt;정규표현식 사용 : 음수 처리를 따로 해주어야 하지만 소수점, 숫자만 포함 등 더 엄밀한 조건을 세워 걸러줄 수 있다. 다만 코드가 알아보기 힘들어 질 수 있고, 엄밀하게 조건을 직접 다 넣어주어야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;1주차 이후 공통 피드백&lt;/h1&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;기본적 Git 명령어 숙지&lt;/li&gt;
&lt;li&gt;Git으로 관리할 자원 고려
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;.gitignore&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;package-lock.json 역할 이해&lt;/li&gt;
&lt;li&gt;commit 메시지를 의미있게 작성
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://meetup.nhncloud.com/posts/106&quot;&gt;https://meetup.nhncloud.com/posts/106&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;commit 메시지에 이슈나 PR 번호를 포함하지 않기 : 원본 저장소의 관련 없는 이슈 또는 PR에 영향을 미칠 수 있어, fork로 작업하는 과정에서는 번호 포함하지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;PR을 만든 후 닫지 않고 추가 커밋 하기&lt;/li&gt;
&lt;li&gt;오류를 찾을 때 출력 함수 대신 디버거 사용하기 : vscode에서 node.js 디버깅하는 법 알아보기&lt;/li&gt;
&lt;li&gt;이름을 통해 의도를 드러내기 : 변수명, 함수명, 클래스명
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;축약하지 않기 : 의도를 드러낼 수 있다면 이름이 길어져도 된다. 문맥 상 중복되는 이름은 제거하자.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;if, for, while, 변수 선언문 사이의 공백도 코딩 컨벤션
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;공백 라인을 의미 있게 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;스페이스와 탭을 혼용하지 않기&lt;/li&gt;
&lt;li&gt;의미 없는 주석을 달지 않기&lt;/li&gt;
&lt;li&gt;코드 포매팅을 사용하기&lt;/li&gt;
&lt;li&gt;JavaScript에서 제공하는 함수, API를 적극 활용
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자열 관리 시 함수를 직접 만들기보다 join() 등을 사용해 간결하게 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;소감 및 후기&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;넘침과 부족함 사이 적당함을 찾기 어려웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리팩토링을 하려 해도 스스로 기준이 잡혀있지 않다는 것을 느꼈다. 함수가 하는 &amp;ldquo;하나의 일&amp;rdquo;의 기준이 무엇인지, 다른 사람들도 읽기 좋은 코드의 기준이 무엇인지 등 특히 객체 지향에 대한 공부를 더 해야겠다.&lt;/p&gt;
&lt;h1&gt;앞으로의 목표&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공통 피드백 사항 중, 다음주차 부터는 디버거 사용하기와 이름을 통해 의도 드러내기를 중점적으로 해야겠다.&lt;/p&gt;</description>
      <category>대외활동</category>
      <category>fe</category>
      <category>우아한테크코스</category>
      <category>우테코</category>
      <category>우테코 7기</category>
      <category>프리코스</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/23</guid>
      <comments>https://turtle-hwan.tistory.com/entry/%EC%9A%B0%EC%95%84%ED%95%9C%ED%85%8C%ED%81%AC%EC%BD%94%EC%8A%A4-7%EA%B8%B0-%ED%94%84%EB%A6%AC%EC%BD%94%EC%8A%A4-1%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C#entry23comment</comments>
      <pubDate>Wed, 30 Oct 2024 22:27:14 +0900</pubDate>
    </item>
    <item>
      <title>인프런 판교 퇴근길 밋업 with 개발바닥 참여 후기</title>
      <link>https://turtle-hwan.tistory.com/entry/%EC%9D%B8%ED%94%84%EB%9F%B0-%ED%8C%90%EA%B5%90-%ED%87%B4%EA%B7%BC%EA%B8%B8-%EB%B0%8B%EC%97%85-with-%EA%B0%9C%EB%B0%9C%EB%B0%94%EB%8B%A5-%EC%B0%B8%EC%97%AC-%ED%9B%84%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;847&quot; data-origin-height=&quot;1056&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FZUhi/btsJQAbM8W7/QwrtpyOmbBn1REljXI9uR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FZUhi/btsJQAbM8W7/QwrtpyOmbBn1REljXI9uR1/img.png&quot; data-alt=&quot;퇴근길 밋업&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FZUhi/btsJQAbM8W7/QwrtpyOmbBn1REljXI9uR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFZUhi%2FbtsJQAbM8W7%2FQwrtpyOmbBn1REljXI9uR1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;499&quot; data-origin-width=&quot;847&quot; data-origin-height=&quot;1056&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-filename=&quot;20240925_171913.jpg&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Kt4Uz/btsJQhXVrKB/dg3s2WK1UXcSg7bHapg9H1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Kt4Uz/btsJQhXVrKB/dg3s2WK1UXcSg7bHapg9H1/img.jpg&quot; data-alt=&quot;가는 길&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Kt4Uz/btsJQhXVrKB/dg3s2WK1UXcSg7bHapg9H1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKt4Uz%2FbtsJQhXVrKB%2Fdg3s2WK1UXcSg7bHapg9H1%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;400&quot; height=&quot;533&quot; data-filename=&quot;20240925_171913.jpg&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;가는 길&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인프런에서 주기적으로 크게 진행하는 행사인 판교 퇴근길 밋업에 드디어 선정되어 다녀오게 되었다!! 아직 학부생인데도 선발되어 정말 감사했고 좋은 경험이었다. 가서 보니 최종 지원자가 713명이었고 이 중 100명에 선발된 것!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 이번엔 블로그와 링크드인 통해서 알고 있었던 인프랩 CTO 향로님과 개발바닥 유튜브 운영하시는 호돌님이 진행하신다 해서 큰 기대를 안고 갔었다. &lt;br /&gt;일정은 개발바닥의 고민 상담 이후 식사하며 네트워킹 순서로 진행되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 특정 주제가 있는 것이 아니라 다양한 개발자 분들의 고민을 미리 신청할 때 받아 10개를 추려 향로님 &amp;amp; 호돌님이 직접 답변해주는 방식이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 두 분 다 오랜 개발 경력 동안 쌓인 게 많으셨는지 답변을 진짜 줄줄이 계속 해주셔서 10개 중 6개밖에 못 끝냈다. ㅋㅋㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뭔가 유명인의 유튜브 라이브 직관하는 기분도 들고 두 분 다 말씀도 잘하시는데다 내용도 알차서 도움이 진짜 많이 되었다. 주로 업무 분야나 커리어, 개발 문화 등의 고민이 있었고, 좋은 말씀들을 많이 해주셔서 기억에 남는 내용 위주로 정리해 보려 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20240925_182522.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/InClO/btsJPE7lSN5/6Cykx6PALw1uVB1vXCA5CK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/InClO/btsJPE7lSN5/6Cykx6PALw1uVB1vXCA5CK/img.jpg&quot; data-alt=&quot;판교 스타트업캠퍼스&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/InClO/btsJPE7lSN5/6Cykx6PALw1uVB1vXCA5CK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FInClO%2FbtsJPE7lSN5%2F6Cykx6PALw1uVB1vXCA5CK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;800&quot; height=&quot;600&quot; data-filename=&quot;20240925_182522.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&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-filename=&quot;20240925_182629.jpg&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6XUc0/btsJRAIUize/Cwk25mjGzKfRNKKHnstTv0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6XUc0/btsJRAIUize/Cwk25mjGzKfRNKKHnstTv0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6XUc0/btsJRAIUize/Cwk25mjGzKfRNKKHnstTv0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6XUc0%2FbtsJRAIUize%2FCwk25mjGzKfRNKKHnstTv0%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;500&quot; height=&quot;667&quot; data-filename=&quot;20240925_182629.jpg&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;4000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;571&quot; data-origin-height=&quot;203&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ijjss/btsJPn5XjSw/zHcdxziWfKWFLyMrZlou50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ijjss/btsJPn5XjSw/zHcdxziWfKWFLyMrZlou50/img.png&quot; data-alt=&quot;준비하시는 개발바닥 분들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ijjss/btsJPn5XjSw/zHcdxziWfKWFLyMrZlou50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIjjss%2FbtsJPn5XjSw%2FzHcdxziWfKWFLyMrZlou50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;178&quot; data-origin-width=&quot;571&quot; data-origin-height=&quot;203&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;준비하시는 개발바닥 분들&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;보상과 커리어&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;이직으로 보상을 높이는 것과, 한 회사에서 근속하는 것 중에 어떤 것이 좋을까라는 첫 질문이다.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자신이 성장할 수 있는 방향을 선택하자&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 분 다 처음에는 엄청 낮은 연봉으로 시작하셨지만 여러 번 이직을 하신 커리어를 갖고 계셨다. 하지만 연봉이 꾸준히 높아진 것은 아니고, 오히려 연봉을 깎고 이직한 경우가 많으셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;경제적 자유는 회사의 직원 신분으로는 얻기 힘들고, 낮은 확률이더라도 어차피 창업의 길로 가야 한다. 그렇다면 자신에게 도움이 되는 방향으로 행동하는 것이 어떨까라는 이야기를 해주셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랫동안 개발자로 일하려면 돈보다는 재미와 흥미가 있어서 일을 해야 하는 것 같다. 무슨 일이든 마찬가지겠지만 흥미 없이 생계를 위해, 돈을 벌기 위해서만 일하는 것은 너무 슬픈 미래일 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직까지 개발이 재밌어서 다행이라는 생각이 들었고, 물론 회사에서 오래 일하면 생각이 달라지겠지만 지금은 빨리 회사에서 주위 좋은 동료들에게 많은 것을 배우고, 기여도 하고, 서비스 출시하고 QA와 사용자 피드백도 받아보고 싶다는 생각이 든다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;일과 삶의 적절한 배분과 권태기 극복&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;일상적인 삶과 개발 관련 자기계발 시간을 어떻게 배분하면 좋을까에 관한 두 번째 질문이다. &lt;br /&gt;질문 중간에 개발바닥 분들은 권태기를 어떻게 극복하나요? 라는 질문도 있었다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유독 개발 분야가 퇴근하고 나서도 공부해야 하고 계속 바뀌는 기술 트랜드를 따라잡으려면 평생 공부해야 한다는 말을 많이 들어온 듯하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 업무 시간 외에도 이슈 터지면 일단 빠르게 해결해야 하는 개발자 특성 상 일과 삶을 명확히 구분짓기 쉽지 않을 거 같은데 10년 넘게 일하신 두 분은 어떻게 하는지 궁금했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 회사 외적으로 뭔가를 추가로 공부하기보단 회사에 조금 더 빨리 가서 코드를 읽어본다거나 (정해놓고 가는 게 아니라 오늘은 쫌 일찍 일어났네? 하는 날에만.. ㅋㅋㅋ), 회사에서 Java spring이 아닌 php로 작성된 코드도 공부해본다거나 하는 방향으로 말씀해주셨던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 두 분이 취미가 개발 블로그 글쓰기에 남는 시간에 개발 유튜브 운영하시는 모습을 가만 보니, 개발이 이미 삶의 일부가 되어 굳이 일과 삶을 구분할 필요가 없을 정도로 잘 섞여서 살고 계신게 아닌가 하는 생각이 들었다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;다른 취미로 열정 돌려놓기 &amp;amp; 시간 정해 놓고 그냥 하기&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;권태기 극복과 관련해서는 향로님이 열정의 아궁이 이론을 설명해주셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아궁이 불씨를 꺼뜨리지 않기 위해 지속적으로 이곳 저곳으로 불씨를 옮겨놓는 것처럼, 열정의 불씨도 꺼뜨리지 않기 위해 꼭 개발이 아니라 다른 취미에도 주기적으로 열정을 옮기는 것이 필요하다는 거다. 이렇듯 개발에 열정이 식었다면 방향성은 달라도 열정은 꺼지지 않게 다른 곳에 잠시 옮겨두라는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 정작 자신은 이렇게 하지 않고, 하기 싫어도 시간을 정해 놓고 그냥 한다고 하셨다 ㅋㅋㅋㅋ&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;회사에서 다른 분야 학습 &amp;amp; 인프라의 중요성&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;희망 분야와 회사 입사해서 맡은 일이 다른 분야일 때 어떤 방향으로 나아가면 좋을지에 대한 세 번째 질문이다.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;배우는 분야에 제한을 두지 말고 현재 배울 수 있는 것에 집중하기&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드 서비스를 희망해서 입사했는데 ai나 devops 쪽 일을 하는 중이라 백엔드 쪽을 더 배우고 싶은데 어떻게 해야 할지 고민이라 하셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글머리로 표시된 것이 답변 내용들이고, 화살표는 개인적인 생각이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배우는 분야에 제한을 두지 말고 현재 회사에서 배울 수 있는 것에 집중하는 것이 중요하다. 회사에서 할 수 없는 건 집에서 해보면 좋다.&lt;/li&gt;
&lt;li&gt;주니어 때, 사고쳐도 괜찮을 때 CI/CD, 모니터링 부터 인프라단까지 다 만져보고 돌려보는 것이 매우 좋은 기회다.&lt;/li&gt;
&lt;li&gt;devops, 인프라는 컴퓨터 구성을 파고들어가는 반면 애플리케이션은 점점 추상화를 쌓아올려 사람과 가까워지고 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 이 말이 정말 공감되었다. ChatGPT 가 나온 이후 이제 개발이 거의 자연어 단계까지 추상화가 되고 있는 상황에서, 과연 개발자로서 차별성을 어디서 찾아야 하나 고민 중이었는데 인프라를 잘 아는 개발자가 되면 확실한 차별성이 갖춰지지 않을까 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;옛날 SSR은 서버 단에서 다 뿌려줬는데 현재는 Next로 프론트에서도 배포, 모니터링, 네트워크 구성, 소켓 등 다 해야 하는 상황이다.&lt;/li&gt;
&lt;li&gt;저연차 때 인프라를 많이 다뤄봐야 고연차 때 폭발적인 성장이 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 과거엔 서비스 구현하려면 온프레미스로 다 만들면서 인프라 다뤄야 했지만 요즘엔 클라우드 서비스도 많고 추상화가 많이 된 듯하다. 오히려 클라우드로 인프라가 추상화 되면서 개발자들이 인프라에 직접 접근하고 잘 이해해야 더 잘 쓸 수 있는 상황이 되었다고 느껴졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;장애가 났을 때 코드만 보느냐 전체 인프라를 다 보느냐 큰 차이가 있다.&lt;/li&gt;
&lt;li&gt;깊게 가려면 처음에 넓게 파야 한다. 장애가 났을 때 해결하려면 결국 넓게 봐야 하니 주변에 보면 넓게 파는 사람들이 많다. 운영 쪽을 아는 사람부터 시니어로 부르기 시작한다.&lt;/li&gt;
&lt;li&gt;향로님 신입 뽑을 때도 그냥 백 프론트만 해온 사람보단 네트워크, 인프라 경험 있는 사람 선호한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 신입인데 어떻게 네트워크, 인프라 경험을 쌓냐구요.. 이런 측면에서 정보보호병으로 전산실에서 일했던 경험이 진짜 운이 좋고 귀중한 경험이라 생각한다. 맨날 주무관님이 농담 삼아 7계층 짜식들이라고 불렀었는데 확실히 2, 3 계층까지 내려가서 네트워크 만져보고 실물 서버 접속해서 관리해보는 경험은 흔치 않다는 것을 사회 나와서 더 체감했다. 이때도 뭐가 크게 안되는 경우는 인프라 문제인 경우가 꽤나 있었고, 열심히 뛰어다니면서 해결했으니 말이다. 깨진 광.. 고장난 광컨.. 안되는 스위치 포트..&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;공부하는 방법&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;책을 통해, 온라인 강의 수강, 야생으로 검색해가며 뭔가 만들기 중 어떤 방법으로 성장하시나요? 라는 네 번째 질문이다.&lt;/blockquote&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;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;공개된 공간에 글을 쓰고, 반박을 받아 수정해보자&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 말을 듣고 감명받아서 나도 &lt;a title=&quot;열심히 블로그 하기&quot; href=&quot;https://turtle-hwan.tistory.com/entry/%EB%B8%94%EB%A1%9C%EA%B7%B8%EC%97%90-%EB%8C%80%ED%95%9C-%EC%82%AC%EA%B2%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;몇 달간 방치했던 블로그에 다시 글을 올리기 시작&lt;/a&gt;했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호돌님은 어떤 앱, 서비스를 만들 목적이 있어야 한다는 말을 해주셨다. 책은 초반에만 보고 이후엔 그 목적을 위해 직접 짜면서 검색으로 문제해결 해나가는 방식을 선호하는데, 파생되는 것을 계속 타고타고 내려가면서 배우면 결국 완성은 못하더라도.. 공부는 많이 된다고 하셨다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;좋은 개발 문화&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;기존엔 좋은 개발 문화란 개발자가 개발에만 집중하게 해주는 것이라 생각했는데 개발만 해서는 일하기 힘들고, 타 부서와 협업하는 시간이 길고 협업 능력도 중요합니다. &lt;br /&gt;이에 대해 개발바닥은 어떻게 생각하시나요? 라는 다섯 번째 질문이었다.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;내가 만들어가는 좋은 회사 문화만이 있을 뿐이지, 좋은 개발 문화가 따로 있는 것이 아니다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호돌님은 회사 출근하자마자 문화에 포함되는 것이라 해주셨다. &lt;br /&gt;내가 하는 것도 기존 회사 문화에 영향을 미치고, 회사 문화에도 영향을 받는 등 내가 회사에서 행동하는 모든 것이 문화에 포함되는 것이라는 말을 해주셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;향로님은 모든 직군이 직군 자체에만 집중할 수 있는 환경을 만들어주면 회사가 성장 가능한가? 라는 질문을 던지셨고, 이렇게 되면 회사가 성장 불가능할 것이라고 답하셨다.&lt;br /&gt;마찬가지로 개발자가 개발에만 집중하려면 다른 직군이 맞춰줘야 할 수밖에 없고, 그러면 좋은 회사 차원에서 좋은 서비스를 제공하기는 불가능하다고 대답하셨다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;회사의 목적은 좋은 서비스와 제품을 만들어 판매하는 것인데 이를 위해선 제품 조직의 성장이 필요하다.&lt;/li&gt;
&lt;li&gt;서비스 장애가 많이 난다면 다른 부서들도 개발 조직에만 서포트하는 것이 맞다.&lt;/li&gt;
&lt;li&gt;그런데 서비스 장애가 없고, 현재 기술 부채는 떠안고 갈 만하다면 개발자는 다른 조직을 서포트 해주는 것이 맞다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;조직과 현재 만들고 있는 제품이 성공하려면 좋은 회사 문화만 있을 뿐이지 좋은 개발 문화가 따로 있는 것이 아니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;어느 정도 궤도에 오른 대기업은 사업 부서가 힘들고, 여기에 중점이 맞추어져 있다.&lt;/li&gt;
&lt;li&gt;초기 스타트업은 디자인, 서비스 마케팅 팀에서 바이럴을 일으켜야 해서 도움이 필요하다.&lt;/li&gt;
&lt;li&gt;스타트업 중반에 성장하며 서비스 확장해야 해서 기술 부채 개선이 필요할 때 개발 부서가 힘들고 서포트 받아야 한다.&lt;/li&gt;
&lt;li&gt;하지만 이 시기만 찾고 개발자 지원만을 바라면 안된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 두 분 다 CTO이셔서 그런지 보는 시각이 개발 팀을 넘어서 회사의 지속가능함에 초점을 두고 계셔서 정말 좋았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;rarr; 이전에 모의면접을 봤을 때 지원자님은 어떤 회사에 들어가고 싶나요? 라는 질문에 막연히 좋은 개발 문화가 갖춰진 회사에 들어가고 싶습니다. 라고 답변했었고, 이에 대해 개선이 필요하다는 평을 받은 적이 있었다. 그동안 나도 개발자 입장에서만 좋은 개발 문화에 대해 생각했었는데 이 통찰력이 담긴 대답들을 듣고 시야가 넓어진 기분이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;성장하는 개발 문화를 만들 수 있는 방법&lt;/h3&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;성장하는 개발 문화와 조직 문화를 어떻게 효과적으로 만들 수 있을까요? 근데 이제 시니어 부재를 곁들인. &lt;br /&gt;이라는 여섯 번째 질문이다.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;주변 사람들과 문화를 바꾸는 사람이 되자&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;향로님이 시니어가 있을수록 좋은 개발문화 만들기 힘들 수 있다, 오히려 주니어들끼리가 좋은 개발문화 만들기 쉽다고 말씀해주셔서 의외였다. 그런데 이유를 듣고 나니 이해가 되었다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연차가 쌓일수록 실패경험이 많이 쌓이고 이는 레퍼런스가 된다. 일반적으로 해도 안될거라거나 이미 실패해본 경험이 있거나 왜 하느냐는 질문이 나오게 되고, 이에 주니어는 시니어 개발자를 설득하기 힘들다.&lt;/li&gt;
&lt;li&gt;신입일 때 같은 신입들을 이상적으로 생각한 개발문화를 만들자고 설득하기가 쉽다.&lt;/li&gt;
&lt;li&gt;나랑 비슷한 연차도 설득 못하는데 더 높은 연차인 시니어 설득이 훨 어렵다&lt;/li&gt;
&lt;li&gt;향로님도 인프런 처음 시작할 때 원래 이렇게 하는 거야.. 라고 말하며 주니어 개발자들에게 새로운 개발 문화들을 도입해서 성공할 수 있었다고 하셨다 ㅋㅋㅋㅋㅋ&lt;/li&gt;
&lt;li&gt;&lt;b&gt;주변 사람들과 문화를 바꾼 사람. 이게 많은 회사가 찾는 사람이다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호돌님은 문화 구성원인 자신부터 스스로 바꾸려 노력하는 것이 가장 중요하다고 말해주셨다. &lt;br /&gt;코드리뷰만 막 도입한다 해서 좋은 문화일 수는 없고, 각자 관심사가 다르고 목표가 다 다르니 차분히 접근해서 천천히 바꿔나가는 것이 좋을 것이다 라고 해주셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이도 공감이 많이 되는 것이 팀플할 때만 봐도 코드리뷰 필수로 한다 해도 결국 팀원들의 관심사가 코드 리뷰에 있는지 코드를 빨리 짜서 제출하는 것에 있는지에 따라 리뷰 퀄리티가 달라지고, 더 나아가 코드 퀄리티까지도 영향을 크게 받는다.&lt;br /&gt;팀원과 많은 대화를 통해 각자 관심사를 파악하고 적절한 기준을 찾아 맞추어 나가는 것이 정말 중요하다 느꼈다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;네트워킹 시간&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 분야에 맞게 12팀으로 나눠 주셨는데, 무려 백 8팀 풀스택 2팀 프론트 2팀이었다. 그 중 프론트 팀에 속해 흥미로운 이야기를 많이 듣고 왔다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;564&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/behC88/btsJQWTfwPq/q9Qo6rxqSq4BEIEVlDdRAK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/behC88/btsJQWTfwPq/q9Qo6rxqSq4BEIEVlDdRAK/img.png&quot; data-alt=&quot;무려 1인 1피자와 음료가 제공되었다. 감사해요 인프랩~&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/behC88/btsJQWTfwPq/q9Qo6rxqSq4BEIEVlDdRAK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbehC88%2FbtsJQWTfwPq%2Fq9Qo6rxqSq4BEIEVlDdRAK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;420&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;564&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;무려 1인 1피자와 음료가 제공되었다. 감사해요 인프랩~&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오신 분들의 연차는 엄청 다양하셨다. 아직 학부생이라고 말씀드리니, 왜 프론트를 선택했냐는 질문이 바로 되돌아왔다&amp;hellip;&lt;br /&gt;학교만 해도 프론트 파는 사람이 별로 없는데 백엔드, 서버 분야가 아무래도 프론트에 비해 꾸준히 수요도 많고 사람도 많지 않은가 싶다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React만 사용하는 분은 없었고, Next.js를 다들 도입해서 사용 중이셨다. 물론 app router와 page router는 반반 정도로 많이 갈렸는데, 특히 app router의 여러 오류에 대한 이야기가 오갔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 동아리와 프로젝트 하면서도 전역 상태 관리의 단점들에 관한 이야기가 나온 적이 있었는데 이 때문인지 기존 전역 상태를 다 뜯어내고 최대한 context API, zustand store 조금 정도로 사용하신다는 분도 계셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마크업 개발자 분이 따로 계신 회사도 꽤 있는 것 같아 신기했다. 디자인 시스템 쪽을 담당해주시는 건지 CSS나 Sass로 뽑아주시는건지 궁금했는데 여쭤볼 기회가 없어 아쉬웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 다른 이야기로는 기억에 의존해서 틀린 내용일수도 있지만, 마크업 개발자 분은 sass 스타일을 한 곳에 모아서 관리하시는 것을 선호하시는 반면 프론트 개발자 입장에서는 그때그때 사용하기 좋게 styled-component 등을 필요할 때 만들어 쓰는 것이 편한 것이 아닌가라는 것이었다. 여기서 관점의 차이가 발생한다 하셨고, 토스 프론트엔드 파이트 클럽에서 들은 CSS vs. CSS-in-JS 이야기와도 겹치는 면이 있는 것 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호돌님이 테이블에 와주셨는데 마침 호돌님이 CTO이신 반려생활에서 프론트엔드 개발자 채용 중이기도 하셔서 어떤 분이 이직, 경력직 채용 시에 회사 코드는 대부분 볼 수 없으니 어떤 것을 주로 보고 뽑느냐고 질문해 주셨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;호돌님 답변으로는 코드를 어떻게 짜는지는 확인할 수 있어야 해서 회사 계정 외에도 깃헙 잔디나 코드가 관리되어 있어야 하고, 그 외에는 프레임워크/라이브러리 등을 써본 경험이 있는지 질문할 것이라 하셨다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;소감&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정신없이 이야기만 듣다보니 마지막에 링크드인 교환을 두 분 밖에 못해서 아쉬웠다.&lt;br /&gt;내용적으로도 기술적으로도 정말 도움이 많이 되는 시간이었고, 학생입장에서는 더더욱 그렇고 회사 다니는 분들 입장에서도 다른 회사의 현직자 분들을 만날 기회가 드문데 이렇게 네트워킹 자리까지 마련해주셔서 아주 값진 시간이었다.&lt;/p&gt;</description>
      <category>대외활동/강연, 세미나</category>
      <category>개발고민</category>
      <category>개발바닥밋업</category>
      <category>인프런</category>
      <category>판교퇴근길밋업</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/22</guid>
      <comments>https://turtle-hwan.tistory.com/entry/%EC%9D%B8%ED%94%84%EB%9F%B0-%ED%8C%90%EA%B5%90-%ED%87%B4%EA%B7%BC%EA%B8%B8-%EB%B0%8B%EC%97%85-with-%EA%B0%9C%EB%B0%9C%EB%B0%94%EB%8B%A5-%EC%B0%B8%EC%97%AC-%ED%9B%84%EA%B8%B0#entry22comment</comments>
      <pubDate>Sun, 29 Sep 2024 18:30:08 +0900</pubDate>
    </item>
    <item>
      <title>React Component와 객체지향의 차이에 관하여</title>
      <link>https://turtle-hwan.tistory.com/entry/React%EC%9D%98-Component%EC%99%80-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;소개글&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;difference between react component and oop.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZDmFG/btsJQ53mm3X/eGhinPxjh097wfdA2meUm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZDmFG/btsJQ53mm3X/eGhinPxjh097wfdA2meUm1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZDmFG/btsJQ53mm3X/eGhinPxjh097wfdA2meUm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZDmFG%2FbtsJQ53mm3X%2FeGhinPxjh097wfdA2meUm1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;225&quot; data-filename=&quot;difference between react component and oop.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;과연 객체지향, OOP에서 말하는 객체와 React Component를 동일선 상에 놓고 봐도 되는가?&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;KUIT 교내 개발 동아리에서 WEB 파트장을 하다 이런 질문을 받게 되었다. 좋은 질문을 남겨준 이름 모를 부원 분께도 감사하며, 파트장을 하며 오히려 알아가는 것이 많아 힘들지만 재밌다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 받은 질문 중에서 가장 많이 찾아보고 고민했음에도, 아직까지 스스로 명확한 답을 내리지 못한 상태이다. 이 질문 덕에 React 공식 문서부터 각종 번역본, React 개발자 분의 블로그(overreact)까지 탐독하게 되었다.&lt;br /&gt;(이 글을 읽는 다른 개발자 분들의 의견도 매우 궁금한 상황이고 틀린 내용이 있다면 꼭 댓글 달아 주시면 정말 감사하겠습니다!!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JS Deep Dive 책을 다 읽고 이해한다면 더 깔끔한 답변이 가능할거라 느꼈고, JS Deep Dive를 다 읽고나서 이 글을 다시 볼 생각이다. 아래는 질문과, 답변했던 내용을 경어체 그대로 옮겨와보았다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;질문&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;리액트를 공부하다가 의문이 생겨서 질문드립니다. &lt;br /&gt;리액트의 가장 기본 단위는 Component라고 하는 것 같은데, 이 Component는 행동(이벤트 핸들러나 로직처리 부분)과 상태로 구성되는 것이라고 배웠습니다. &lt;br /&gt;사실상 UI 출력도 어떻게 보면 출력을 하는 &quot;행동&quot;으로 볼 수 있을 것 같은데, 그러면 OOP에서 말하는 &quot;객체&quot;와 크게 다르지 않은 건가요?? &lt;br /&gt;둘 다 독립적인 단위로서 행동과 상태로 구성되니까요.. GPT는 객체와 컴포넌트는 그 개념이 사실상 동일하지만 사용되는 관점과 맥락에 따라 용어가 다를 뿐인 것이라고 하는데, 의견이 궁금합니다. &lt;br /&gt;만약에 객체와 컴포넌트가 동일한 것이라면, 객체는 익숙한 개념이라 컴포넌트를 객체로 바라보면서 학습하면 좀 더 쉬워질 것 같아 질문드립니다&lt;/blockquote&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;답변&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 객체지향, OOP는 &lt;a href=&quot;https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D_%ED%8C%A8%EB%9F%AC%EB%8B%A4%EC%9E%84&quot;&gt;패러다임&lt;/a&gt;의 한 분야입니다.&amp;nbsp;OOP의 특징으로는 추상화, 상속, 다형성, 캡슐화가 있죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React component는 UI를 추상화하기 위한 목적으로 만들어졌고, 자식 컴포넌트도 만들어 data를 전달할 수 있고, 데이터를 캡슐화 가능하며, Typescript를 통해 다형성도 만족시킬 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 &lt;a href=&quot;https://ko.legacy.reactjs.org/docs/composition-vs-inheritance.html&quot;&gt;상속 구조보다는 합성을 사용하는 걸 권장&lt;/a&gt;하네요. 그리고 props를 통한 data도 한 쪽 방향으로밖에 전달하지 못합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React는 객체지향을 목적으로 만들어진 것은 아니고 선언적 패러다임을 통해 UI를 더 쉽게 만들기 위한 목적으로 만들어졌다고 생각합니다. 개발자가 UI 랜더링에 대한 책임은 React한테 위임하고, 컴포넌트만 선언하면 되는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React 코드를 잘 작성하고, component를 잘 설계하고 관리하기 위한 방법을 생각하다 보니 OOP와 비슷해지게 되고, SOLID와 같은 OOP 원칙들을 가져와서 적용하게 된 것이 아닌가 싶습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유명한 객체지향 원칙인 SOLID를 React에서 어떻게 적용하는지는 &lt;a href=&quot;https://dev-boku.tistory.com/entry/번역-React에-SOLID-원칙-적용하기&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이 글을 참고&lt;/a&gt;하면 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 React는 class component 생성 방식을 따르다 v16.8에서 hook이 등장하면서 현재는 function component 생성 방식으로 바뀌었습니다.&amp;nbsp;이 이유도 개발자에게 더 추상화되고 편리한 UI 개발 환경을 제공하기 위해서라고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;class component를 만들기 위해서는 function 방식보다 알아야 하는 것도 많고, component lifecycle도 상당히 복잡했었거든요.&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;그래서 이런 여러가지 이유를 보아 컴포넌트 == (객체 지향에서 말하는) 객체 라고 단정지어 말하기는 어렵다고 생각합니다. component들이 객체의 몇몇 특성을 띠고, 일부 OOP 패러다임을 차용해 쓰고 있다 라고 생각하는 것이 어떨까 싶습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저도 고민하던 부분이어서 이리저리 많이 찾아보긴 했는데 내용은 많이 없는 것 같네요..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;추가내용&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;React를 처음 시작하는 부원 분이 헷갈리실까봐 답변 내용에는 달지 않았지만 내용을 추가해본다면 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Javascript는 프로토타입 기반 객체지향이라 사실 function도 객체이고, 이에 따르면 component도 객체라고 부를 수 있다. 여기서부터 아주 혼란스러워졌다. 그러면 일반적인(JAVA, C++) 객체 지향과 뭐가 다르지? 프로토타입은 도대체 뭐지? 함수형 프로그래밍(FP)??&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 차이에 대해서는 Javasript Deep Dive 책에 자세히 나와있고, 마침 해당 책 스터디도 하게 되었으니 여기서 여러 의견을 나누고 깊게 학습할 것이 기대된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아직 JS에 대한 이해가 완벽하지 않아 헷갈리고 잘 모르는 부분이 많았고, 나중에 다시 봤을 때 더 많은 내용을 보충할 수 있길 기대하며 글을 마친다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;lt;참고 문서들&amp;gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://legacy.reactjs.org/blog/2013/06/05/why-react.html&quot;&gt;https://legacy.reactjs.org/blog/2013/06/05/why-react.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://medium.com/@admin_1497/리액트-개발자는-객체지향-패러다임을-적용할-수-없는걸까-부제-리액트에서-객체지향-프로그래밍-31fc98f7c5fb&quot;&gt;https://medium.com/@admin_1497/리액트-개발자는-객체지향-패러다임을-적용할-수-없는걸까-부제-리액트에서-객체지향-프로그래밍-31fc98f7c5fb&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://overreacted.io/why-do-we-write-super-props/&quot;&gt;https://overreacted.io/why-do-we-write-super-props/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://overreacted.io/how-does-react-tell-a-class-from-a-function/&quot;&gt;https://overreacted.io/how-does-react-tell-a-class-from-a-function/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pozafly.github.io/react/declarative-meaning-of-react-rendering-process/&quot;&gt;https://pozafly.github.io/react/declarative-meaning-of-react-rendering-process/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://velog.io/@cychann/React-Class-컴포넌트-vs-Function-컴포넌트&quot;&gt;https://velog.io/@cychann/React-Class-컴포넌트-vs-Function-컴포넌트&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kciter.so/posts/polymorphic-react-component/&quot;&gt;https://kciter.so/posts/polymorphic-react-component/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://react.dev/learn/thinking-in-react&quot;&gt;https://react.dev/learn/thinking-in-react&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>프로그래밍/Frontend (React, Javascript, Typescript)</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/21</guid>
      <comments>https://turtle-hwan.tistory.com/entry/React%EC%9D%98-Component%EC%99%80-%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC#entry21comment</comments>
      <pubDate>Sun, 29 Sep 2024 08:00:12 +0900</pubDate>
    </item>
    <item>
      <title>상단 메뉴 바 고정(Fixed Menu) 구현 방법들과, content에 margin-top을 주면 위험한 이유 (feat. margin collapsing)</title>
      <link>https://turtle-hwan.tistory.com/entry/Fixed-Menu-%EB%A9%94%EB%89%B4-%EB%B0%94-%EC%83%81%EB%8B%A8-%EA%B3%A0%EC%A0%95-%EA%B5%AC%ED%98%84-%EC%8B%9C-content%EC%97%90-margin-top%EC%9D%84-%EC%A3%BC%EB%A9%B4-%EC%9C%84%ED%97%98%ED%95%9C-%EC%9D%B4%EC%9C%A0-feat-margin-collapsing</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;소개&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;KUIT 교내 개발 동아리에서 WEB 파트장을 맡아 운영 중이다. WEB 파트 부원들에게 준 2주차 미션이&amp;nbsp;당근마켓 화면 HTML, CSS로 클론코딩하기였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미션 결과물 코드리뷰를 하다 좋은 질문들이 많이 나와 공부가 많이 되었는데, 그 중에 fixed menu, 메뉴 바 상단 고정 구현 할 때 menu bar 아래 content에 margin-top을 주면 위험할수도 있겠다는 생각이 들었고, 그 이유에 대해서도 많이 찾아보게 되어서 글을 써보았다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Fixed_Menu.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b5CZMY/btsJQ2etaGc/5f1U1qtTikLpAH793tKb7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b5CZMY/btsJQ2etaGc/5f1U1qtTikLpAH793tKb7K/img.png&quot; data-alt=&quot;코드리뷰 하다 찾게 된 margin collapsing&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b5CZMY/btsJQ2etaGc/5f1U1qtTikLpAH793tKb7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb5CZMY%2FbtsJQ2etaGc%2F5f1U1qtTikLpAH793tKb7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;300&quot; data-filename=&quot;Fixed_Menu.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;코드리뷰 하다 찾게 된 margin collapsing&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;질문&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드와 함께 보는 것이 편할 수도 있을 것 같아 추가한 &lt;a href=&quot;https://github.com/Konkuk-KUIT/KUIT4_Web-FrontEnd/pull/33#discussion_r1777592446&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;github discussion 주소&lt;/a&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만들고자 하는 화면은 아래 이미지처럼 당근마켓의 한 화면을 구현하되, 스크롤을 내려도 맨 상단 바가 항상 위에 고정되도록 하는 것이었다. 일반적인 블로그나 사이트에서도 많이 쓰이는 fixed menu 구현이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;375&quot; data-origin-height=&quot;263&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buBsRR/btsJQI1A0xR/f5x3rnBLi5kWNEIkgSk6c1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buBsRR/btsJQI1A0xR/f5x3rnBLi5kWNEIkgSk6c1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buBsRR/btsJQI1A0xR/f5x3rnBLi5kWNEIkgSk6c1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbuBsRR%2FbtsJQI1A0xR%2Ff5x3rnBLi5kWNEIkgSk6c1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;375&quot; height=&quot;263&quot; data-origin-width=&quot;375&quot; data-origin-height=&quot;263&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;blockquote data-ke-style=&quot;style3&quot;&gt;질문은&amp;nbsp;&lt;br /&gt;.main__header 에 top 0px 속성을 주니 content 요소에서 margin,padding 속성으로 위치 조정이 가능한 반면, top 0px 속성을 주지 않았을 때 content 요소에서 margin-top 속성을 주니 fixed를 준 main__header 요소가 밑으로 함께 내려오는 이유를 알 수 있을까요? 였다.&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;367&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OX7CA/btsJPAKH5W3/YCkQi0Can4ze3wM0KY538K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OX7CA/btsJPAKH5W3/YCkQi0Can4ze3wM0KY538K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OX7CA/btsJPAKH5W3/YCkQi0Can4ze3wM0KY538K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOX7CA%2FbtsJPAKH5W3%2FYCkQi0Can4ze3wM0KY538K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;954&quot; height=&quot;367&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;367&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #0070d1; text-align: start;&quot; href=&quot;https://www.daleseo.com/css-position-fixed-navigation/&quot;&gt;유명 개발자 분이 fixed menu를 구현한 블로그&lt;/a&gt;에서도 당연한 듯이 margin이 아닌 padding-top을 사용하시길래 그 이유가 정말 궁금해졌다. 생각보다 이유를 정리한 글을 찾기 힘들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;해결&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;결론부터 말하자면 &lt;b&gt;margin-collapsing &lt;/b&gt;이 발생해 body element에 영향을 주었기 때문이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, absolute position은 veiwport (브라우저에서 보이는 화면 기준)으로 positioning 된다. 그리고 브라우저에 렌더링 될 때 다음 단계를 거친다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;item-list와 부모 요소 body tag가 margin collapsing이 발생해서 body의 viewport 상 시작 위치가 상단 52px부터가 된다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;908&quot; data-origin-height=&quot;347&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sv7TT/btsJQUgAPMj/2hOFTu50XnaokXPlyGX2i0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sv7TT/btsJQUgAPMj/2hOFTu50XnaokXPlyGX2i0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sv7TT/btsJQUgAPMj/2hOFTu50XnaokXPlyGX2i0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fsv7TT%2FbtsJQUgAPMj%2F2hOFTu50XnaokXPlyGX2i0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;908&quot; height=&quot;347&quot; data-origin-width=&quot;908&quot; data-origin-height=&quot;347&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/ol&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;main__header에 absolute 속성을 붙이더라도 offset(top, left, bottom, right)을 지정하지 않거나 auto로 두면 position이 static일 때의 위치와 일치하도록 offset이 자동 지정된다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;885&quot; data-origin-height=&quot;676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Valyn/btsJPQ7gCza/vRucviLd4aikkCdxwEALFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Valyn/btsJPQ7gCza/vRucviLd4aikkCdxwEALFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Valyn/btsJPQ7gCza/vRucviLd4aikkCdxwEALFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FValyn%2FbtsJPQ7gCza%2FvRucviLd4aikkCdxwEALFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;885&quot; height=&quot;676&quot; data-origin-width=&quot;885&quot; data-origin-height=&quot;676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/ol&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;static의 기준점은 body 기준이므로, body element의 시작 위치부터 지정되게 된다. 따라서 따로 top:0 속성을 주지 않으면 body와 함께 밀린 상태로 있게 된다.&lt;/li&gt;
&lt;li&gt;문제는 main__header에 top: 0을 줘도 사실상 body에는 margin-collapsing이 일어난 상태가 유지된다!!!!!!!&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;600&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qT07X/btsJQf6RhSD/O2dmMTaMbjJ2i5XbgWRD50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qT07X/btsJQf6RhSD/O2dmMTaMbjJ2i5XbgWRD50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qT07X/btsJQf6RhSD/O2dmMTaMbjJ2i5XbgWRD50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqT07X%2FbtsJQf6RhSD%2FO2dmMTaMbjJ2i5XbgWRD50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;897&quot; height=&quot;600&quot; data-origin-width=&quot;897&quot; data-origin-height=&quot;600&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;새로운 문제 발생&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제목에서 적은 Fixed Menu, 메뉴 바 상단 고정 구현 시 content에 margin-top을 주면 위험한 이유는 바로 위 4번 과정에서처럼 body가 margin-collapsing이 발생해 밀려나기에, header는 따로 top: 0을 주어 맞춘다 하더라도 다른 body 기준으로 배치되는 element들이 이상해질 가능성이 높기 때문이다!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 이를 해결하기 위해 어떻게 해야 할까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 그렇다면&lt;span style=&quot;letter-spacing: 0px;&quot;&gt; body에 추가 속성을 줘서 margin-collapsing을 방지하거나, item-list에 margin-top이 아닌, padding-top을 주는 것이 추후 오류 예방을 위해 훨씬 좋을 수도 있을 것이라 답변했다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;padding-top 으로 해결하거나, 헤더 동일 크기의 빈 element를 두어 해결&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;다른 사이트들을 찾아보니 네이버와 카카오는 padding-top으로 해결하는 것을 볼 수 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 &lt;a href=&quot;https://toss.im/career/jobs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;토스의 구현&lt;/a&gt;을 보니&lt;span style=&quot;letter-spacing: 0px;&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;955&quot; data-origin-height=&quot;186&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AKuwU/btsJPdI1ag6/CqwVTfyAkc4Jcc0AQCM0Kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AKuwU/btsJPdI1ag6/CqwVTfyAkc4Jcc0AQCM0Kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AKuwU/btsJPdI1ag6/CqwVTfyAkc4Jcc0AQCM0Kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAKuwU%2FbtsJPdI1ag6%2FCqwVTfyAkc4Jcc0AQCM0Kk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;955&quot; height=&quot;186&quot; data-origin-width=&quot;955&quot; data-origin-height=&quot;186&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;굳이 padding 대신 빈 요소를 두는 이유가 이해가 안 되어 현직자 친구의 정말 깔끔한! 답변을 받았다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;padding 대신 동일 크기 빈 요소를 두는 이유는&lt;br /&gt;&lt;b&gt;&quot;본래 목적에 맞지 않는 영역에 관여하는 것을 방지&quot;&lt;/b&gt; 하고, &lt;br /&gt;&quot;padding으로 content에서 top menu까지 신경쓰기보다, 상단메뉴에서 구현할 때 아예 자기 자신의 높이만큼 차지하는 빈요소를 두는 것이 &lt;b&gt;관심사 분리에 더 적합&lt;/b&gt;&quot; 하기 때문이라 한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내 경험으로도 화면 구현할 때 여러 단계 아래 있는 content에서 padding을 일일히 계산하느라 애먹은 적이 있었고, 특히 반응형을 나중에 마이그레이션 할 때도 어느 padding들이 합쳐진 건지 이전 개발자 분이 적어둔 주석을 보고 겨우 찾아냈던 기억이 떠올랐다. 이를 생각해보면 토스가 관심사 분리 측면에서 정말 좋은 접근법을 고안한 것이라 느꼈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진짜 좋은 질문이었고 이 덕분에 생각지도 않고 쓰던 것을 한 번 더 돌아보며 자세히 파고들 기회였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;참고링크&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/53215944/why-does-my-header-moves-down-when-i-set-it-fixed&quot;&gt;https://stackoverflow.com/questions/53215944/why-does-my-header-moves-down-when-i-set-it-fixed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/54774549/why-arent-my-absolutely-fixed-positioned-elements-located-where-i-expect&quot;&gt;https://stackoverflow.com/questions/54774549/why-arent-my-absolutely-fixed-positioned-elements-located-where-i-expect&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.daleseo.com/css-position-absolute/&quot;&gt;https://www.daleseo.com/css-position-absolute/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>프로그래밍/Frontend (React, Javascript, Typescript)</category>
      <category>Code review</category>
      <category>CSS</category>
      <category>HTML</category>
      <category>KUIT</category>
      <category>margin collapsing</category>
      <category>toss 구현</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/20</guid>
      <comments>https://turtle-hwan.tistory.com/entry/Fixed-Menu-%EB%A9%94%EB%89%B4-%EB%B0%94-%EC%83%81%EB%8B%A8-%EA%B3%A0%EC%A0%95-%EA%B5%AC%ED%98%84-%EC%8B%9C-content%EC%97%90-margin-top%EC%9D%84-%EC%A3%BC%EB%A9%B4-%EC%9C%84%ED%97%98%ED%95%9C-%EC%9D%B4%EC%9C%A0-feat-margin-collapsing#entry20comment</comments>
      <pubDate>Sat, 28 Sep 2024 22:30:32 +0900</pubDate>
    </item>
    <item>
      <title>블로그에 대한 사견</title>
      <link>https://turtle-hwan.tistory.com/entry/%EB%B8%94%EB%A1%9C%EA%B7%B8%EC%97%90-%EB%8C%80%ED%95%9C-%EC%82%AC%EA%B2%AC</link>
      <description>&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;블로그 글은 일단 쓰고 공개하는 것이 중요하다.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&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;블로그를 위한 노력들을 돌이켜 보면 첫 시작은 네이버 블로그였다. 2021년쯤 한창 개발자 열풍이 불고 기술블로그를 너도나도 하는 시기에 개발 공부와 함게 시작했었고, 지금 보니 글을 140여개나 올렸었다. 이걸로 군대 면접 때 쏠쏠히 써먹었지만 입대하고서는 버려졌다..&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이때도 네이버 블로그가 마크다운을 지원 안 하는 것 때문에 노션 글을 옮기기가 너무 불편해서 github blog를 직접 만들려다가 마음에 안 들어서 테마 가져오고 뒤엎고를 반복했었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;그러다 velog도 써봤는데 마크다운 인식은 가장 잘 해주지만 테마 자유도가 떨어지고 기능이 아직 많이 없는 데다 이미지도 복붙이 안 되는 문제 때문에 tistory로 넘어오게 되었다. 그런데 티스토리도 이미지는 여전히 불편하다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;왜 어려울까. 블로그 글쓰기를 왜 망설이는 걸까? 하면 단순 개념을 작성하는 것이 과연 의미가 있을까? 라는 의문이 들어서였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;노션과 옵시디언에 정리된 메모들을 블로그 글로 다시 한 번 정제하는 것도 생각보다 많은 시간과 노력이 들어간다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;그런데 이미 다른 블로그에 올라온 글이면 굳이 내가 새롭게 정리해서 올려야 하는가? 이것마저도 &amp;ldquo;바퀴의 재발명&amp;rdquo;이 되어버리는 것에 아닌가.&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;이 생각이 바뀌게 된 계기는 현재 인프랩 CTO인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://jojoldu.tistory.com/775&quot;&gt;향로님의 블로그 글&lt;/a&gt;을 읽고서였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;2015년부터 2024년 현재까지 매년 블로그를 시작하신 분들은 정말 많았지만 그걸 3년, 5년 유지하는 분들은 정말 극소수이다. &amp;hellip; 3년, 5년이 지나면 같이 시작한 거의 대부분의 사람들은 없어지고 그때까지 꾸준히 해온 것 만으로도 충분히 존중 받을 수 있다.&amp;rdquo; 라는 구절이 정말 공감되었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;또 인상적이었던 구절은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&amp;ldquo;블로그로 인한 많은 기회와 경험&quot;&lt;/b&gt;과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&amp;ldquo;평생 가져갈 수 있는 좋은 취미&amp;rdquo;&lt;/b&gt;가 생긴다는 것이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;결국 관점의 차이지만 남에게 보여주기 위한 글보다는 자기만족을 위한 글을 쓰는 것이 더 큰 동력원이 된다고 느꼈다. 블로그 뿐만이 아니다. 노션, 옵시디언에 메모하는 것, 더 나아가 공부마저도 남이 아닌 내가 궁금해서 했을 때가 가장 효과적이었으니 말이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;아니, 지금 와서 솔직히 말하자면 저 글을 읽고서도 귀찮다는 핑계로, 일이 많다는 핑계로 몇 달간 블로그를 방치했었다. 지금 쓰고 있는 글도 사실 1년 전쯤 적어둔 메모들이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;생각이 조금 더 바뀐 것은 이번 주 수요일에 인프런 퇴근길 밋업에 가서 향로님을 직접 뵙고 이야기를 들은 이후였다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;향로님이 성장하면서 지금 위치까지 오기에 가장 큰 영향을 주었던 것은 무엇인가요? 라는 질문에&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&amp;ldquo;공개된 공간에 글을 쓰고 반박을 받아 다시 수정하는 과정을 많이 거쳤기 때문이다&amp;rdquo;&lt;/b&gt;라고 대답해주셨다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이 뿐만이 아니라 여러 질문들에 답변하실 때 정말 통찰력 있고 공감되는 답을 많이 해주셨고, 이는 평소에 고민을 많이 하고 글로써 풀어내는 과정을 자주 거치셨기 때문이 아닌가 생각이 들었다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;나부터가 1년을 채 가지 못했기 때문에 느리더라도 꾸준히 가는 것을 목표로 삼고 향로님을 본받아 시간을 정해놓고, 퇴고에 힘을 빼서라도 꾸준히 글을 올려야겠다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;블로그는 공공장소일까?&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;경계가 참 애매하다. 공개된 자료를 누구나 사용하면서 의견도 남길 수 있으니 공공장소라고 할 수 있지만 블로그의 경우 자신만의 공간을 직접 새로 만든 것이니 개인적이라고도 볼 수 있겠다. 공개된 일기장 정도로 볼 수 있을까.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;블로그에 글을 쓴다는 건 사람들이 잘 지나다니지 않아 잊혀진 길모퉁이를 얻어 글을 써서 벽보를 붙이고 그림을 그리는 기분이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;어느 외딴 곳의 한적한 시골, 더 나아가 교통편과 인적이 극히 드문 무인도에 가까운 섬이라고 봐도 될 것이다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;정보의 바다 속 어딘가에 떠 있지만 아직은 아무도 모를 이 무인도를 잘 가꾸어 좋은 휴양지가 될 수 있길 기대해본다.&lt;/p&gt;</description>
      <category>사색과 잡념 사이</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/19</guid>
      <comments>https://turtle-hwan.tistory.com/entry/%EB%B8%94%EB%A1%9C%EA%B7%B8%EC%97%90-%EB%8C%80%ED%95%9C-%EC%82%AC%EA%B2%AC#entry19comment</comments>
      <pubDate>Sat, 28 Sep 2024 21:55:52 +0900</pubDate>
    </item>
    <item>
      <title>Asrock H110M-HDV 보드 + Linux Ubuntu 22.04  WOL (wake on lan) 설정하기</title>
      <link>https://turtle-hwan.tistory.com/entry/Asrock-H110M-HDV-%EB%B3%B4%EB%93%9C-Linux-Ubuntu-2204-WOL-wake-on-lan-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0</link>
      <description>&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;lt;목차&amp;gt;&lt;br /&gt;1. Asrock H110M BIOS 설정&lt;br /&gt;2. Ubuntu 22.04 WOL 설정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;안 쓰는 컴퓨터에 우분투를 깔아서 홈서버를 만든 적이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 24시간 동안 켜 놓으니 전기세나 발열은 둘째 치더라도 소음이 너무 커서 잠자기 힘들어서 해결할 방법을 고민했었다. 물론 구형 HDD에 구형 쿨러를 쓰는 탓도 있겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 쿨러교체 + HDD를 SSD로 교체, M.2 NVMe to SATA converter가 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 본체를 바깥으로 빼고 벽단자 잘 찾아서 공유기 연결하기 or 선을 길게 빼기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. WOL 설정하고 필요할 때만 켜서 쓰기 or 취침 시간에 자동 종료, 자동 켜지게 구성하기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번은 소음 크기는 줄일 수 있어도 소음 자체는 줄이지 못하고, &lt;br /&gt;2번은 사용 중인 것을 제외하고 살아 있는 벽단자가 없었다. 블로그 글들에선 집 단자함에서 이리저리 연결만 해주면 된다고 하던데 랜선에 주기도 안 되어 있었고 구조 파악을 실패했다. 전산실의 랜추적기가 그리워졌다..&lt;br /&gt;결국 남은 방법이 3번인데 6개월 전 쯤 WOL 관련 설정은 다 해두었는데도 안돼서 묵혀놓고 있다가 다시 구글링하면서 이번에 성공했다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;iptime 공유기에 물려놓고 DDNS 설정을 해둔 다음,&amp;nbsp;ipTIME WOL 앱에 DDNS 주소를 등록하면 휴대폰으로 어디서든 서버를 킬 수 있게 된다!!&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. Asrock H110M BIOS 설정&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2가지 설정을 enabled로 바꿔줘야 한다.&lt;br /&gt;이전에는 두 번째 설정을 안 바꿔줘서 WOL이 안됐던 것이었다..!!!!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1)&amp;nbsp; Advanced mode (F6) -&amp;gt; Boot -&amp;gt;&amp;nbsp; Boot from onboard lan ==&amp;gt; [enabled]&lt;br /&gt;설명 : Allow the system to be waked up by the onboard LAN.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20240428_105656.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Pg3WM/btsGYZ0NeYX/sYaDtJsLSapGcogSPUcpWk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Pg3WM/btsGYZ0NeYX/sYaDtJsLSapGcogSPUcpWk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Pg3WM/btsGYZ0NeYX/sYaDtJsLSapGcogSPUcpWk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPg3WM%2FbtsGYZ0NeYX%2FsYaDtJsLSapGcogSPUcpWk%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;746&quot; height=&quot;560&quot; data-filename=&quot;20240428_105656.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;Advanced mode (F6)&lt;/span&gt; -&amp;gt; Advanced -&amp;gt; ACPI configuration -&amp;gt; PCIE Devices Power On&amp;nbsp; ==&amp;gt; [enabled]&lt;br /&gt;설명 : Allow the system to be waked up by a PCIE device and enable wake on LAN.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;20240428_105753.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFQm8P/btsGYznPyzJ/5SniuXcqvLKMjJTsAWKmMk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFQm8P/btsGYznPyzJ/5SniuXcqvLKMjJTsAWKmMk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFQm8P/btsGYznPyzJ/5SniuXcqvLKMjJTsAWKmMk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFQm8P%2FbtsGYznPyzJ%2F5SniuXcqvLKMjJTsAWKmMk%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;752&quot; height=&quot;564&quot; data-filename=&quot;20240428_105753.jpg&quot; data-origin-width=&quot;4000&quot; data-origin-height=&quot;3000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Asrock H110M BIOS 공식 문서 : &lt;a href=&quot;https://download.asrock.com/Manual/H110M-HDV.pdf&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://download.asrock.com/Manual/H110M-HDV.pdf&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://masachi.tistory.com/311&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://masachi.tistory.com/311&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1714275523217&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;asrock H110M wol(wake on lan) 설정&quot; data-og-description=&quot;이번에 회사 컴퓨터를 스카이레이크 cpu가 달린 컴터를 바꾼 관계로 지방컴터를 서울에서 관리하기 위해 wol 설정을 했다. 그런데... 그런데!!! 안되는 것이었다. 이유인 즉슨 단순히 bios에서 wol 기&quot; data-og-host=&quot;masachi.tistory.com&quot; data-og-source-url=&quot;https://masachi.tistory.com/311&quot; data-og-url=&quot;https://masachi.tistory.com/311&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/0f0GX/hyVVLFGiJ3/IRPVRKYwSrxem99UqkQK1K/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bvC0lx/hyVVIoEN4n/XYQekj7Y0YnW8KiFo0oyq0/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800&quot;&gt;&lt;a href=&quot;https://masachi.tistory.com/311&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://masachi.tistory.com/311&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/0f0GX/hyVVLFGiJ3/IRPVRKYwSrxem99UqkQK1K/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bvC0lx/hyVVIoEN4n/XYQekj7Y0YnW8KiFo0oyq0/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;asrock H110M wol(wake on lan) 설정&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번에 회사 컴퓨터를 스카이레이크 cpu가 달린 컴터를 바꾼 관계로 지방컴터를 서울에서 관리하기 위해 wol 설정을 했다. 그런데... 그런데!!! 안되는 것이었다. 이유인 즉슨 단순히 bios에서 wol 기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;masachi.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 글의 작성자에게 정말 감사하다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style7&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;2. Ubuntu 22.04&amp;nbsp;&amp;nbsp;WOL 설정&lt;/span&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인보드 설정과 함께 Ubuntu에서도 WOL 관련 설정을 해주어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) wol과 네트워크 관련 패키지를 설치한다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #000000; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;sudo apt-get install net-tools ethtool wakeonlan&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) ifconfig 명령어로 현재 사용 중인 이더넷 네트워크 인터페이스 이름을 알아낸다. 현재 ip가 찍혀 있는 인터페이스이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3) 인터페이스 이름이 enp3s0 이라면 다음 명령어를 실행한 결과에서 &quot;Wake-on: g&quot; 라고 출력되어야 한다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #000000; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;sudo ethtool -s enp3s0 wol g
sudo ethtool enp3s0&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4) 다만 위의 ethtool 설정 내용은 재부팅 시 초기화 되므로, root 권한으로 해당 위치 파일에 다음 내용을 추가한다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #000000; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;sudo vi /etc/network/interfaces&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #000000; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;post-up /sbin/ethtool -s 인터페이스명 wol g
post-down /sbin/ethtool -s 인터페이스명 wol g&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5) Ubuntu 18.04 이상부터는 시스템 실행 시 자동으로 위 명령어가 실행되도록 systemd service도 만들어 주어야 한다.&lt;/p&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #000000; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;sudo vi /etc/systemd/system/wol.service&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #000000; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;[Unit]
Description=Configure Wake-up on LAN

[Service]
Type=oneshot
ExecStart=/sbin/ethtool -s 인터페이스명 wol g

[Install]
WantedBy=basic.target&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;bash&quot; style=&quot;color: #000000; text-align: left;&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;sudo systemctl enable /etc/systemd/system/wol.service&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;a href=&quot;https://velog.io/@deogicorgi/%EC%9A%B0%EB%B6%84%ED%88%ACUbuntu-%ED%99%88%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%EA%B8%B01-WOL-%EC%84%A4%EC%A0%95&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://velog.io/@deogicorgi/%EC%9A%B0%EB%B6%84%ED%88%ACUbuntu-%ED%99%88%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%EA%B8%B01-WOL-%EC%84%A4%EC%A0%95&lt;/a&gt;&lt;/p&gt;</description>
      <category>프로그래밍/홈서버</category>
      <category>H110M</category>
      <category>Ubuntu 22.04</category>
      <category>wol</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/18</guid>
      <comments>https://turtle-hwan.tistory.com/entry/Asrock-H110M-HDV-%EB%B3%B4%EB%93%9C-Linux-Ubuntu-2204-WOL-wake-on-lan-%EC%84%A4%EC%A0%95%ED%95%98%EA%B8%B0#entry18comment</comments>
      <pubDate>Sun, 28 Apr 2024 13:27:33 +0900</pubDate>
    </item>
    <item>
      <title>[JavaScript, Node.js] 프론트엔드(JavaScript Runtime)에서의 Race Condition</title>
      <link>https://turtle-hwan.tistory.com/entry/JavaScript-Nodejs-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9CJavaScript-Runtime%EC%97%90%EC%84%9C%EC%9D%98-Race-Condition</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;JS와 관련해서 흥미로운 사실을 찾았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템프로그래밍이나 OS 수업에서 한 번쯤 들어봤을 race condition이 프론트엔드에서도 발생할 수 있다는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Race Condition?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;race condition은 두 개 이상의 프로세스, 스레드가 공유되는 자원(critical section)에 접근해서 값을 쓰려고 할 때 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;race condition이 발생하면 공유 자원의 값이 의도치 않게 변경되는 문제점이 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드에서의 레이스 컨디션은 실제 바뀐 값으로 권한 상승 등이 일어날 수 있어 CTF에서도 종종 출제되고 보안적으로 상당히 심각하게 다뤄지는 문제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 프론트엔드에서는 보여지는 화면만 바뀌는 것이니 그렇게까지 위험하지는 않을 것 같고, Race Condition이 발생할 수 있는지를 생각해본 적이 없었는데 이번 기회에 알아보게 되었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;JS Engine은 싱글 스레드인데 어떻게 Race Condition이 발생하는가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 JS Engine은 싱글 스레드 기반인데 어디서 레이스 컨디션이 발생하는 건지 궁금증이 생겼다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JS 런타임의 안의 memory heap과 call stack은 싱글 스레드 상에서 동작하니 문제가 없어 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 JS 런타임의&amp;nbsp;DOM, fetch 등 Web API 스레드들이 callback queue에 동시에 접근하는 것이니, callback queue에서 race condition이 발생하는 것일까?&lt;/p&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에서 Race Condition이 발생하는 예시이다.&lt;/p&gt;
&lt;pre id=&quot;code_1712825371675&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var x = 1;

async function foo() {
    var y = x;
    await setTimeout(100); // whatever async here
    x = y+1;
}

//비동기 함수를 동시에 실행하면 Race condition이 발생한다.
await Promise.all([foo(), foo(), foo()]);
console.log(x); // 2


//동시에 실행되지 않고 순차적이라면 다음과 같다.
await foo();
await foo();
await foo();
console.log(x); // 4&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 Stackoverflow 답변을 참고하면, 동시성(Concurrency)과 병렬성(Parallel)에 관해 JS는 싱글 스레드 기반이므로 스레드 병렬성은 없지만 비동기 함수를 가져서 동시성을 가지고 작동한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동시성 때문에 JS에서 여러 비동기 요청(fetch, setTimeout ..)을 여러 번 보냈을 때 그 응답은 순서가 보장되지 않는다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 await 등으로 순서를 보장해 주지 않으면 DOM이나 변수에 원하지 않는 값이 들어갈 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;510&quot; data-origin-height=&quot;274&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgCBKn/btsGzlO8Ynu/DqqBS7AqDNxx2KzQgOMkS0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgCBKn/btsGzlO8Ynu/DqqBS7AqDNxx2KzQgOMkS0/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgCBKn/btsGzlO8Ynu/DqqBS7AqDNxx2KzQgOMkS0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgCBKn%2FbtsGzlO8Ynu%2FDqqBS7AqDNxx2KzQgOMkS0%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;510&quot; height=&quot;274&quot; data-origin-width=&quot;510&quot; data-origin-height=&quot;274&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/73202786/does-this-javascript-example-create-race-conditions-to-the-extent-that-they&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://stackoverflow.com/questions/73202786/does-this-javascript-example-create-race-conditions-to-the-extent-that-they&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712825245409&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;Does this JavaScript example create &amp;ldquo;race conditions&amp;rdquo;? (To the extent that they can exist in JavaScript)&quot; data-og-description=&quot;I am aware JavaScript is single-threaded and technically can&amp;rsquo;t have race conditions, but it supposedly can have some uncertainty because of async and the event loop. Here&amp;rsquo;s an oversimplified example:&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/73202786/does-this-javascript-example-create-race-conditions-to-the-extent-that-they&quot; data-og-url=&quot;https://stackoverflow.com/questions/73202786/does-this-javascript-example-create-race-conditions-to-the-extent-that-they&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Dec9s/hyVPMjecRX/diWZoEjPzIPbKneAN0BSk0/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316,https://scrap.kakaocdn.net/dn/Gdak5/hyVMYexbHU/zlsT9Vz3ujKq1H1SqLOgmk/img.jpg?width=510&amp;amp;height=274&amp;amp;face=0_0_510_274,https://scrap.kakaocdn.net/dn/XYPaf/hyVPLECuO5/6ugb63Huk4Onf6AiCWZwp1/img.jpg?width=372&amp;amp;height=374&amp;amp;face=0_0_372_374&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/73202786/does-this-javascript-example-create-race-conditions-to-the-extent-that-they&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/73202786/does-this-javascript-example-create-race-conditions-to-the-extent-that-they&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Dec9s/hyVPMjecRX/diWZoEjPzIPbKneAN0BSk0/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316,https://scrap.kakaocdn.net/dn/Gdak5/hyVMYexbHU/zlsT9Vz3ujKq1H1SqLOgmk/img.jpg?width=510&amp;amp;height=274&amp;amp;face=0_0_510_274,https://scrap.kakaocdn.net/dn/XYPaf/hyVPLECuO5/6ugb63Huk4Onf6AiCWZwp1/img.jpg?width=372&amp;amp;height=374&amp;amp;face=0_0_372_374');&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;Does this JavaScript example create &amp;ldquo;race conditions&amp;rdquo;? (To the extent that they can exist in JavaScript)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;I am aware JavaScript is single-threaded and technically can&amp;rsquo;t have race conditions, but it supposedly can have some uncertainty because of async and the event loop. Here&amp;rsquo;s an oversimplified example:&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;JS 엔진을 쓰는 Node.js에서의 Race Condition과 이를 막기 위한 방법&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Race Condition을 막는 방법은 SystemProgramming에서 나오는 것과 같다. 공유되는 자원 Critical Section에 접근하는 것을 한 번에 하나씩 접근하도록 제한하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;JS 엔진을 쓰는 Node.js 계열에서도 레이스 컨디션을 막기 위한 mutex, semaphore 라이브러리가 구현되어 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://fourjae.tistory.com/entry/Nodejs-Race-Condition&quot;&gt;https://fourjae.tistory.com/entry/Nodejs-Race-Condition&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712825176802&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] Race Condition과 해결 원리&quot; data-og-description=&quot;본 글에서는 Node.js에서 발생할 수 있는 Race Condition에 대해 작성하려고 한다. + 첫 프로젝트인 새싹챌린지를 진행하면서 겪었던 일까지 1. Race Condition이란? Race Condition(경쟁 상태) 혹은 경쟁 조건이&quot; data-og-host=&quot;fourjae.tistory.com&quot; data-og-source-url=&quot;https://fourjae.tistory.com/entry/Nodejs-Race-Condition&quot; data-og-url=&quot;https://fourjae.tistory.com/entry/Nodejs-Race-Condition&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bTbhtK/hyVPV8jfXC/oPo1apj7OUZJU8QQFcAmw0/img.png?width=800&amp;amp;height=537&amp;amp;face=0_0_800_537,https://scrap.kakaocdn.net/dn/dhYP0c/hyVPXyhJlC/gEErKgsWAcT0dqx8Cohyrk/img.png?width=800&amp;amp;height=537&amp;amp;face=0_0_800_537,https://scrap.kakaocdn.net/dn/bTby8o/hyVM0cnqLP/1g6z8teBNHl85MCchKwIlk/img.png?width=1496&amp;amp;height=1006&amp;amp;face=0_0_1496_1006&quot;&gt;&lt;a href=&quot;https://fourjae.tistory.com/entry/Nodejs-Race-Condition&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://fourjae.tistory.com/entry/Nodejs-Race-Condition&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bTbhtK/hyVPV8jfXC/oPo1apj7OUZJU8QQFcAmw0/img.png?width=800&amp;amp;height=537&amp;amp;face=0_0_800_537,https://scrap.kakaocdn.net/dn/dhYP0c/hyVPXyhJlC/gEErKgsWAcT0dqx8Cohyrk/img.png?width=800&amp;amp;height=537&amp;amp;face=0_0_800_537,https://scrap.kakaocdn.net/dn/bTby8o/hyVM0cnqLP/1g6z8teBNHl85MCchKwIlk/img.png?width=1496&amp;amp;height=1006&amp;amp;face=0_0_1496_1006');&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] Race Condition과 해결 원리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;본 글에서는 Node.js에서 발생할 수 있는 Race Condition에 대해 작성하려고 한다. + 첫 프로젝트인 새싹챌린지를 진행하면서 겪었던 일까지 1. Race Condition이란? Race Condition(경쟁 상태) 혹은 경쟁 조건이&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;fourjae.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;조금 더 찾아보니 threading과 concurrency(동시성)은 별개의 개념이고, 싱글 스레드에서도 동시적 접근으로 인한 race condition이 발생할 수도 있다고 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;싱글스레드 Node.js에서 race condition 예시 :&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://stackoverflow.com/questions/21438207/can-node-js-code-result-in-race-conditions&quot;&gt;https://stackoverflow.com/questions/21438207/can-node-js-code-result-in-race-conditions&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712825043577&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;Can node.js code result in race conditions?&quot; data-og-description=&quot;From what I read, race conditions occur when different threads try to change a shared variable, which can result in a value that's not possible with any serial order of execution of those threads. ...&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/21438207/can-node-js-code-result-in-race-conditions&quot; data-og-url=&quot;https://stackoverflow.com/questions/21438207/can-node-js-code-result-in-race-conditions&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/LypSq/hyVPWsB7La/K3r0EKwkVLmsVkMf4rJllk/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/21438207/can-node-js-code-result-in-race-conditions&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/21438207/can-node-js-code-result-in-race-conditions&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/LypSq/hyVPWsB7La/K3r0EKwkVLmsVkMf4rJllk/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316');&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;Can node.js code result in race conditions?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;From what I read, race conditions occur when different threads try to change a shared variable, which can result in a value that's not possible with any serial order of execution of those threads. ...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;참고 자료&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@pjc0247/프론트엔드와-Race-Condition&quot;&gt;https://velog.io/@pjc0247/프론트엔드와-Race-Condition&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712825030740&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;프론트엔드와 Race Condition&quot; data-og-description=&quot;간단히 말해서 두 개 이상의 스레드가 하나의 공유 자원에 접근해서 일어나는 상태(혹은 그로 인해 발생하는 버그) 라고 생각하시면 됩니다.레&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@pjc0247/프론트엔드와-Race-Condition&quot; data-og-url=&quot;https://velog.io/@pjc0247/프론트엔드와-Race-Condition&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cKeLw7/hyVPRriODq/wmx06woTYzUjWgyBzM5OI0/img.jpg?width=576&amp;amp;height=1280&amp;amp;face=0_0_576_1280,https://scrap.kakaocdn.net/dn/ial75/hyVPIA7XM1/TVDrmWPPXU1dw7IK4tdKa1/img.jpg?width=576&amp;amp;height=1280&amp;amp;face=0_0_576_1280,https://scrap.kakaocdn.net/dn/bqYnE6/hyVMO3437q/CYaxstgqk4IKgkvg4TIePK/img.png?width=283&amp;amp;height=283&amp;amp;face=0_0_283_283&quot;&gt;&lt;a href=&quot;https://velog.io/@pjc0247/프론트엔드와-Race-Condition&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@pjc0247/프론트엔드와-Race-Condition&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cKeLw7/hyVPRriODq/wmx06woTYzUjWgyBzM5OI0/img.jpg?width=576&amp;amp;height=1280&amp;amp;face=0_0_576_1280,https://scrap.kakaocdn.net/dn/ial75/hyVPIA7XM1/TVDrmWPPXU1dw7IK4tdKa1/img.jpg?width=576&amp;amp;height=1280&amp;amp;face=0_0_576_1280,https://scrap.kakaocdn.net/dn/bqYnE6/hyVMO3437q/CYaxstgqk4IKgkvg4TIePK/img.png?width=283&amp;amp;height=283&amp;amp;face=0_0_283_283');&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;프론트엔드와 Race Condition&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;간단히 말해서 두 개 이상의 스레드가 하나의 공유 자원에 접근해서 일어나는 상태(혹은 그로 인해 발생하는 버그) 라고 생각하시면 됩니다.레&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://tecoble.techcourse.co.kr/post/2021-09-12-race-condition-handling/&quot;&gt;https://tecoble.techcourse.co.kr/post/2021-09-12-race-condition-handling/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712825029958&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;비동기 처리 시 race condition 고려하기&quot; data-og-description=&quot;비동기 처리 시 race condition&amp;hellip;&quot; data-og-host=&quot;tecoble.techcourse.co.kr&quot; data-og-source-url=&quot;https://tecoble.techcourse.co.kr/post/2021-09-12-race-condition-handling/&quot; data-og-url=&quot;https://tecoble.techcourse.co.kr/post/2021-09-12-race-condition-handling/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/937vW/hyVMX00r6e/DrymiJgguKNfRdyIbZFTS1/img.jpg?width=275&amp;amp;height=183&amp;amp;face=0_0_275_183,https://scrap.kakaocdn.net/dn/IoFof/hyVMLzv5KB/lvbQ3UHxtByacn30qjiGx1/img.jpg?width=275&amp;amp;height=183&amp;amp;face=0_0_275_183&quot;&gt;&lt;a href=&quot;https://tecoble.techcourse.co.kr/post/2021-09-12-race-condition-handling/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://tecoble.techcourse.co.kr/post/2021-09-12-race-condition-handling/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/937vW/hyVMX00r6e/DrymiJgguKNfRdyIbZFTS1/img.jpg?width=275&amp;amp;height=183&amp;amp;face=0_0_275_183,https://scrap.kakaocdn.net/dn/IoFof/hyVMLzv5KB/lvbQ3UHxtByacn30qjiGx1/img.jpg?width=275&amp;amp;height=183&amp;amp;face=0_0_275_183');&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;비동기 처리 시 race condition 고려하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;비동기 처리 시 race condition&amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;tecoble.techcourse.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://jsremote.jobs/tutorials/race-condition/&quot;&gt;https://jsremote.jobs/tutorials/race-condition/&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712825035959&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;What is the race condition in JavaScript? | Web developer jobs&quot; data-og-description=&quot;What is race condition in details, and more definitive JavaScript guides and tutorials on JS-Remote-Jobs.&quot; data-og-host=&quot;jsremote.jobs&quot; data-og-source-url=&quot;https://jsremote.jobs/tutorials/race-condition/&quot; data-og-url=&quot;https://jsremote.jobs/race-condition/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://jsremote.jobs/tutorials/race-condition/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jsremote.jobs/tutorials/race-condition/&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;What is the race condition in JavaScript? | Web developer jobs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;What is race condition in details, and more definitive JavaScript guides and tutorials on JS-Remote-Jobs.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jsremote.jobs&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category>프로그래밍/Frontend (React, Javascript, Typescript)</category>
      <category>CS</category>
      <category>javascript</category>
      <category>RaceCondition</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/17</guid>
      <comments>https://turtle-hwan.tistory.com/entry/JavaScript-Nodejs-%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9CJavaScript-Runtime%EC%97%90%EC%84%9C%EC%9D%98-Race-Condition#entry17comment</comments>
      <pubDate>Thu, 11 Apr 2024 18:11:44 +0900</pubDate>
    </item>
    <item>
      <title>정주영 창업경진대회 13 (정창경13) 설명회 후기   - 디스콰이엇 박현솔 대표님, EO 김태용 대표님 강연 내용 정리</title>
      <link>https://turtle-hwan.tistory.com/entry/%EC%A0%95%EC%A3%BC%EC%98%81-%EC%B0%BD%EC%97%85%EA%B2%BD%EC%A7%84%EB%8C%80%ED%9A%8C-13-%EC%A0%95%EC%B0%BD%EA%B2%BD-%EC%84%A4%EB%AA%85%ED%9A%8C-%EB%94%94%EC%8A%A4%EC%BD%B0%EC%9D%B4%EC%97%87-%EB%B0%95%ED%98%84%EC%86%94-%EB%8C%80%ED%91%9C%EB%8B%98-EO-%EA%B9%80%ED%83%9C%EC%9A%A9-%EB%8C%80%ED%91%9C%EB%8B%98-%EA%B0%95%EC%97%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;창업에 적극적인 친구 덕에 24.04.01에 마루180 지하에서 진행된 정창경 설명회에 가게 되었다.&lt;br /&gt;디스콰이엇과 EO의 존재를 원래 알고 이용하면서 어떤 생각으로 이런 서비스를 만들었을지 정말 궁금했었는데 이번 기회에 관련된 이야기를 들을 수 있어 좋았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기대보다 큰 울림과 인사이트를 얻었고, 웹 상에서 떠도는 창업 관련 글보다 더 구체적이었다.&lt;br /&gt;실제로 실패를 겪으며 여러 시도 끝에 성공한 창업가 분들 자신의 경험담을 직접 듣는다는 것의 의미가 컸다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;1부 디스콰이엇 박현솔 대표님&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메이커들의 막막함을 해결하기 위해 디스콰이엇을 만들었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;창업을 위해 필요한 요소 4가지&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;시장에서 간과되는 문제&lt;/li&gt;
&lt;li&gt;내가 진정성을 느끼는 문제&lt;/li&gt;
&lt;li&gt;타깃 유저 접근성 (타깃 유저가 우리 서비스를 쉽게 접근할 수 있어야 한다)&lt;/li&gt;
&lt;li&gt;개발력 보유 &amp;rArr; 말보다 실물로 보여줄 수 있어 효과적! (개발을 잘 하는 것보다 노코드, 로우코드 툴을 적극적으로 사용해서 빠르게 프로토타입을 만들어 내는 것이 중요하다)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Do things that do not scale&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Do Things that do not scale 이라는 문구를 예로 들어 설명했다. 초기 사용자를 데려오기 위해 발로 뛰며 노력하고, 초기 사용자를 붙잡기 위해 노력해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;아래 링크에 이 말에 대한 더 자세한 설명이 되어 있다.&lt;br /&gt;&lt;a href=&quot;https://medium.com/delightroom/do-things-that-dont-scale-6876c5682a75&quot;&gt;확장 가능하지 않은 일을 하라 (Do things that don&amp;rsquo;t scale)&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712823921773&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;확장 가능하지 않은 일을 하라 (Do things that don&amp;rsquo;t scale)&quot; data-og-description=&quot;이 글은 Paul graham의 Do things that don&amp;rsquo;t scale을 한글 번역한 글입니다. 의역 또는 오역이 있을 수 있습니다. 혹시 잘못된 부분이 있다면 지적 환영입니다. 중간중간 강조 되어있는 부분은 제가 공감&quot; data-og-host=&quot;medium.com&quot; data-og-source-url=&quot;https://medium.com/delightroom/do-things-that-dont-scale-6876c5682a75&quot; data-og-url=&quot;https://medium.com/delightroom/do-things-that-dont-scale-6876c5682a75&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/VBd2J/hyVMMSH2eQ/QrLWbBubMeIAHPfosj8Hv1/img.png?width=990&amp;amp;height=794&amp;amp;face=0_0_990_794,https://scrap.kakaocdn.net/dn/bDqRDU/hyVPP1jR9i/lYZqUoxvVmCoTw6owI2Mr1/img.jpg?width=1358&amp;amp;height=764&amp;amp;face=0_0_1358_764,https://scrap.kakaocdn.net/dn/byzwP8/hyVMPaOGzh/qUwldsg5Rwq53zQeWC6KxK/img.png?width=1178&amp;amp;height=638&amp;amp;face=0_0_1178_638&quot;&gt;&lt;a href=&quot;https://medium.com/delightroom/do-things-that-dont-scale-6876c5682a75&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://medium.com/delightroom/do-things-that-dont-scale-6876c5682a75&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/VBd2J/hyVMMSH2eQ/QrLWbBubMeIAHPfosj8Hv1/img.png?width=990&amp;amp;height=794&amp;amp;face=0_0_990_794,https://scrap.kakaocdn.net/dn/bDqRDU/hyVPP1jR9i/lYZqUoxvVmCoTw6owI2Mr1/img.jpg?width=1358&amp;amp;height=764&amp;amp;face=0_0_1358_764,https://scrap.kakaocdn.net/dn/byzwP8/hyVMPaOGzh/qUwldsg5Rwq53zQeWC6KxK/img.png?width=1178&amp;amp;height=638&amp;amp;face=0_0_1178_638');&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;확장 가능하지 않은 일을 하라 (Do things that don&amp;rsquo;t scale)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 글은 Paul graham의 Do things that don&amp;rsquo;t scale을 한글 번역한 글입니다. 의역 또는 오역이 있을 수 있습니다. 혹시 잘못된 부분이 있다면 지적 환영입니다. 중간중간 강조 되어있는 부분은 제가 공감&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;medium.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존 서비스보다 10배 좋은 것을 만들어야 팔린다.&lt;br /&gt;서비스 품질 = 기능x감정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기능은 기존 제품을 이기기 힘들다. 따라서 감정을 건드려야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디스콰이엇을 운영하면서 초기에 자신의 프로덕트를 소개한 사람들에게 프로덕트에 대한 report를 일일히 작성해서 전달했다. 이 방법으로 더 많은 기회를 얻을 수 있었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;동료 모집&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;디스콰이엇을 성장시키면서 그 과정을 모두 기록해서 공개해왔었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;동료를 모집할 때 가장 중요하게 봤던 것.&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내적 동기 : 자기 경험을 토대로 자신만의 인사이트가 있고, 이것이 디스콰이엇이 추구하는 방향과 비슷한지를 확인했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;외적 동기 : 사업성, 비즈니스만을 추구하는 사람은 뽑지 않았다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;JTBD(job to do done)를 해소하는 핵심 액션을 찾아라&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JTBD : 특정 상황에서 고객이 해결하고자 하는 문제&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람들이 느끼는 어려움을 잘 찾아서 해소하는 방법을 제시하라.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Unique insight를 담은 MVP를 만들어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미개척 시장 vs 포화 시장 각각 다르게 접근해야 한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;PMF prodict market fit 의 6가지 기술&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;타깃 유저&lt;/li&gt;
&lt;li&gt;문제 정의 JTBD&lt;/li&gt;
&lt;li&gt;해결책 (UX)&lt;/li&gt;
&lt;li&gt;차별점&lt;/li&gt;
&lt;li&gt;고객 유입 채널&lt;/li&gt;
&lt;li&gt;BM&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;개발 스펙 설계&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;core loop와 user flow를 설계하라.&lt;br /&gt;core loop는 보통 게임 개발 시에 쓰이는 용어인데 유저에게 어떤 서비스 이용 동기를 부여해서 어떻게 붙잡을 것인가에 관한 용어이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;airbnb의 core loop 예시&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Action. 방 올리기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Reward. 여행객 렌트 문의, 렌트 수익 발생 가능성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Expansion. 실제 렌트 성공, 더 많은 렌트&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 내용을 듣고 특히 창업으로 성공하기 위해서 단순한 구현(OOI)보다 사람들이 겪는 문제를 잘 설정하고 정의한 다음, 어떻게 해결할지 분석(OOA)하고 디자인(OOD) 하는 것이 더 중요하다 느꼈다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;데이터 측정 / 소통 방안&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정량적 측정 : 구글 애널리틱스 등&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정성적 측정 : 특히 소통 창구를 마련해서 실 가용자들의 이야기를 듣는 것이 중요하다! 디스콰이엇은 단톡방과 이메일도 제공했다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;2부 EO 김태용 대표님&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;23살부터 창업을 시작했고, 여러 시도 끝에 지금 이 자리에 오게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;art share : 예술가들이 작품 올리고 소개할 수 있는 공간&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인기가 많은 작품들 &amp;rarr; 직접 팔릴 만한 제품을 선별해서 굿즈 제작해서 판매했다. 위글위글 플랫폼 탄생.&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;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;h2 data-ke-size=&quot;size26&quot;&gt;unfair adventage&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자신만의 unfair adventage를 만들어야 한다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;unfair adventage는 다른 사람에게 없고 나에게만 있는 남들이 불공평하게 여길 만한 장점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;남들보다 내가 확연히 잘하는 것은 내가 맡아서 하고, 못하는 것은 그걸 잘하는 사람을 찾아서 맡기는 게 효율적인 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://sungmooncho.com/2018/11/16/unfair-advantage/&quot;&gt;unfair adventage에 관한 실리콘밸리 창업가 조성문님의 좋은 글&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712823932219&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;불공평한 장점 Unfair Advantage&quot; data-og-description=&quot;3년 전인가, 회사를 시작하던 초기 시절에 Start Up (스타트업)이라는 팟캐스트를 정말 재미있게 들었다. 이미 너무 유명한 팟캐스트이고, 이 블로그를 통해서도 한 번 설명한 적이 있지만, 다시 간&quot; data-og-host=&quot;sungmooncho.com&quot; data-og-source-url=&quot;https://sungmooncho.com/2018/11/16/unfair-advantage/&quot; data-og-url=&quot;https://sungmooncho.com/2018/11/16/unfair-advantage/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/0BGE5/hyVMZLjYnf/V8Wblw9kWnqlQueqT98Cw0/img.jpg?width=1200&amp;amp;height=799&amp;amp;face=0_0_1200_799,https://scrap.kakaocdn.net/dn/bLGzhh/hyVPP1jSiX/hgB6zr7muhOdclD6QYhBQK/img.jpg?width=640&amp;amp;height=426&amp;amp;face=0_0_640_426&quot;&gt;&lt;a href=&quot;https://sungmooncho.com/2018/11/16/unfair-advantage/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://sungmooncho.com/2018/11/16/unfair-advantage/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/0BGE5/hyVMZLjYnf/V8Wblw9kWnqlQueqT98Cw0/img.jpg?width=1200&amp;amp;height=799&amp;amp;face=0_0_1200_799,https://scrap.kakaocdn.net/dn/bLGzhh/hyVPP1jSiX/hgB6zr7muhOdclD6QYhBQK/img.jpg?width=640&amp;amp;height=426&amp;amp;face=0_0_640_426');&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;불공평한 장점 Unfair Advantage&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;3년 전인가, 회사를 시작하던 초기 시절에 Start Up (스타트업)이라는 팟캐스트를 정말 재미있게 들었다. 이미 너무 유명한 팟캐스트이고, 이 블로그를 통해서도 한 번 설명한 적이 있지만, 다시 간&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;sungmooncho.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;42서울의 모토인 life is unfair가 떠오른다. 어차피 삶에서 기회는 불공평하기에 나에게 맞는 기회가 주어졌을 때 놓치지 않을 수 있는 나만의 장점을 키워나가야 할 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;한 번도 시도하지 않은 더 큰 도전을 하라&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 큰 도전을 할 때 쌓이는 특별한 경험과 데이터가 나를, 회사를 더 발전시켜 줄 것이다.&lt;/p&gt;
&lt;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 data-ke-size=&quot;size26&quot;&gt;꿈의 밀도가 중요하다.&lt;/h2&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;3부 질의응답&lt;/h1&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;실패 경험&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람과의 관계에서 오는 상처가 클 수 있다. 좋은 인간관계가 중요하고, 이를 딛고 일어서는 것도 중요하다.&lt;/p&gt;
&lt;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;h2 data-ke-size=&quot;size26&quot;&gt;성과 측정 기준을 어떻게 잡으면 좋은가&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예술의 일상화를 목표로 패션, 의류 관련 창업가 분의 질문이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무신사/유니클로 등 대형 플랫폼 형태가 아니라 감각적, 예술적인 것을 추구한다면 정량적인 지표를 찾기 힘들 수밖에 없다. VC에게 설명도 힘들다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기에는 정량적 지표 숫자에 빠지지 말고, 정성적 지표에 집중하는 것이 좋다. 팀 분위기를 살리며 즐겁다는 기세를 가져가는 것이 베스트이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;머릿속 idea를 어떻게 사업화 하는가?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PMF를 생각하자. 시장이 제품을 원하는지 알아봐야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;배울 것이 없는 실패는 시간 낭비이다. 실패를 있는 그대로 마주해라.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;남이 원하는 것을 찾는 능력. 이런 창업가적 사고는 창업 활동을 하면서 자신의 ego가 부서지고 다시 만들어지는 과정을 거치며 탄생하는 것 같다. (데미안이 생각나는 이야기다..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;알아봐 주는 사람들이 생기고, co-founder가 합류하는 등 제품 출시 전에도 사업은 성장 가능하다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;4부 정주영창업경진대회, 정창경 13 소개&lt;/h1&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;2023년 기준 1219팀 지원, 87:1 경쟁률, 사업자 등록 유지율 79%, 투자 유치율 21%&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;h2 data-ke-size=&quot;size26&quot;&gt;QnA&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;p data-ke-size=&quot;size16&quot;&gt;정성평가 항목이 많은 이유는 현재까지의 정량 지표는 이미 다들 잘 갖추어진 경우가 많았기 때문이다. BM은 기본 전제이고, +a 요소를 심사하기 위해 넣었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현직 VC분들이 심사를 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀이 서비스에 얼마나 진심인지, 대표의 기업가 정신을 중요하게 본다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지원서 내는 시점에 사업자 등록증이 없다면 도전 트랙을 선택하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사업 시작 이유 항목에는 궁극적 목표, 더 큰 요소를 적어도 된다. 정창경 참가 이유 항목에 정창경 기간 내에 달성 가능한 현실적 목표를 적으면 좋다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Concept. 모험이 없으면 큰 발전도 없다. - 아산 정주영&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고 링크&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://startup.asan-nanum.org/#detail&quot;&gt;정창경 13 지원 링크&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://disquiet.io/@asannanum/makerlog/%EC%A0%95%EC%A3%BC%EC%98%81-%EC%B0%BD%EC%97%85%EA%B2%BD%EC%A7%84%EB%8C%80%ED%9A%8C-13-%EC%B0%B8%EA%B0%80-%EC%8A%A4%ED%83%80%ED%8A%B8%EC%97%85-%EB%AA%A8%EC%A7%91-4-22&quot;&gt;디스콰이엇 정창경 소개 글&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1712823941614&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;정주영 창업경진대회 13 참가 스타트업 모집! (~4/22) | Disquiet*&quot; data-og-description=&quot;안녕하세요, 아산나눔재단입니다. &amp;lt;모험을 시작하는 곳, 정주영 창업경진대회 13&amp;gt; 모집이 시작되었습니다.실패를 두려워하지 않고, 도전 정신으로 창업의 여정을 나서는 모험가들을 찾습니다! &amp;nbsp;&quot; data-og-host=&quot;disquiet.io&quot; data-og-source-url=&quot;https://disquiet.io/@asannanum/makerlog/%EC%A0%95%EC%A3%BC%EC%98%81-%EC%B0%BD%EC%97%85%EA%B2%BD%EC%A7%84%EB%8C%80%ED%9A%8C-13-%EC%B0%B8%EA%B0%80-%EC%8A%A4%ED%83%80%ED%8A%B8%EC%97%85-%EB%AA%A8%EC%A7%91-4-22&quot; data-og-url=&quot;https://disquiet.io/@asannanum/makerlog/%EC%A0%95%EC%A3%BC%EC%98%81-%EC%B0%BD%EC%97%85%EA%B2%BD%EC%A7%84%EB%8C%80%ED%9A%8C-13-%EC%B0%B8%EA%B0%80-%EC%8A%A4%ED%83%80%ED%8A%B8%EC%97%85-%EB%AA%A8%EC%A7%91-4-22&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://disquiet.io/@asannanum/makerlog/%EC%A0%95%EC%A3%BC%EC%98%81-%EC%B0%BD%EC%97%85%EA%B2%BD%EC%A7%84%EB%8C%80%ED%9A%8C-13-%EC%B0%B8%EA%B0%80-%EC%8A%A4%ED%83%80%ED%8A%B8%EC%97%85-%EB%AA%A8%EC%A7%91-4-22&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://disquiet.io/@asannanum/makerlog/%EC%A0%95%EC%A3%BC%EC%98%81-%EC%B0%BD%EC%97%85%EA%B2%BD%EC%A7%84%EB%8C%80%ED%9A%8C-13-%EC%B0%B8%EA%B0%80-%EC%8A%A4%ED%83%80%ED%8A%B8%EC%97%85-%EB%AA%A8%EC%A7%91-4-22&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;정주영 창업경진대회 13 참가 스타트업 모집! (~4/22) | Disquiet*&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요, 아산나눔재단입니다. &amp;lt;모험을 시작하는 곳, 정주영 창업경진대회 13&amp;gt; 모집이 시작되었습니다.실패를 두려워하지 않고, 도전 정신으로 창업의 여정을 나서는 모험가들을 찾습니다! &amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;disquiet.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1712823940157&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;전국에 기업가 정신과 창업 문화를 확산하고, 유망한 스타트업을 발굴하여 지원하는 아산나눔재단의 실전형 창업 지원 프로그램&quot; data-og-host=&quot;startup.asan-nanum.org:443&quot; data-og-source-url=&quot;https://startup.asan-nanum.org/#detail&quot; data-og-url=&quot;http://startup.asan-nanum.org/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bxAK3O/hyVMNKSaX2/VsK5nMdR5X3892lCpIFPKk/img.png?width=600&amp;amp;height=315&amp;amp;face=0_0_600_315,https://scrap.kakaocdn.net/dn/sZERw/hyVMR0NyAv/CkK0phuC7J0ypVcyE0NVHK/img.png?width=600&amp;amp;height=315&amp;amp;face=0_0_600_315&quot;&gt;&lt;a href=&quot;https://startup.asan-nanum.org/#detail&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://startup.asan-nanum.org/#detail&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bxAK3O/hyVMNKSaX2/VsK5nMdR5X3892lCpIFPKk/img.png?width=600&amp;amp;height=315&amp;amp;face=0_0_600_315,https://scrap.kakaocdn.net/dn/sZERw/hyVMR0NyAv/CkK0phuC7J0ypVcyE0NVHK/img.png?width=600&amp;amp;height=315&amp;amp;face=0_0_600_315');&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;전국에 기업가 정신과 창업 문화를 확산하고, 유망한 스타트업을 발굴하여 지원하는 아산나눔재단의 실전형 창업 지원 프로그램&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;startup.asan-nanum.org:443&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>대외활동/강연, 세미나</category>
      <category>정창경</category>
      <category>정창경13</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/16</guid>
      <comments>https://turtle-hwan.tistory.com/entry/%EC%A0%95%EC%A3%BC%EC%98%81-%EC%B0%BD%EC%97%85%EA%B2%BD%EC%A7%84%EB%8C%80%ED%9A%8C-13-%EC%A0%95%EC%B0%BD%EA%B2%BD-%EC%84%A4%EB%AA%85%ED%9A%8C-%EB%94%94%EC%8A%A4%EC%BD%B0%EC%9D%B4%EC%97%87-%EB%B0%95%ED%98%84%EC%86%94-%EB%8C%80%ED%91%9C%EB%8B%98-EO-%EA%B9%80%ED%83%9C%EC%9A%A9-%EB%8C%80%ED%91%9C%EB%8B%98-%EA%B0%95%EC%97%B0#entry16comment</comments>
      <pubDate>Thu, 11 Apr 2024 17:25:00 +0900</pubDate>
    </item>
    <item>
      <title>[KUIT 3기 Web] 2주차(5 - 完) - 당근마켓 화면(CSS) 클론 하기 및 트러블 슈팅</title>
      <link>https://turtle-hwan.tistory.com/entry/KUIT-3%EA%B8%B0-Web-2%EC%A3%BC%EC%B0%A85-%E5%AE%8C-%EB%8B%B9%EA%B7%BC%EB%A7%88%EC%BC%93-%ED%99%94%EB%A9%B4CSS-%ED%81%B4%EB%A1%A0-%ED%95%98%EA%B8%B0-%EB%B0%8F-%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;2주차 과제는 주어진 피그마대로 당근마켓 화면1을 기본 HTML + CSS로 동일하게 구현하기였다.&lt;/li&gt;
&lt;li&gt;git repo fork 후 github pages로 배포해서 화면을 확인할 수 있게 했고, 결과물은 다음과 같다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://turtle-hwan.github.io/KUIT3_Web-FrontEnd/week2/turtlehwan/daangn_1/index.html&quot;&gt;미션 결과물-당근마켓 화면1 링크&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/Konkuk-KUIT/KUIT3_Web-FrontEnd/assets/67897841/2960f4e6-2d33-4c9b-bf5d-c46f498feafe&quot; alt=&quot;image&quot; /&gt;&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h1&gt;트러블 슈팅&lt;/h1&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;h2 data-ke-size=&quot;size26&quot;&gt;Issue 1&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;문제&lt;/code&gt;&lt;br /&gt;상단 header가 고정이 안되어서 fixed로 고정했다.&lt;br /&gt;그런데 fixed로 고정한 다음, header에 width 100% 를 주면 header가 화면보다 조금 커져서 화면 밖으로 튀어나간다?!?!?!&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &amp;rarr; &lt;b&gt;&lt;code&gt;display: flex;   justify-content: space-between;&lt;/code&gt;&lt;/b&gt; 해당 속성일 때 튀어나간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제도 box-sizing: border-box; 문제였다....!!!!!&lt;br /&gt;width 100%가 content를 현재 화면의 100%로 맞추어 버려서 padding 길이만큼 더 튀어나갔던 것!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말로 box-sizing: border-box;를 전체에 적용하고 시작하는 것이 덜 헷갈리겠다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-webkit-fill-available 으로 chrome에서 width: 100%를 대체할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;scss&quot;&gt;&lt;code&gt;  position: fixed;
  top: 0px;
  z-index: 1;
  width: 100%;
  box-sizing: border-box;&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;width 100% 대신 left, right 0을 주어도 된다. 이는 box-sizing과 관계없이 항상 잘 동작한다.
&lt;pre class=&quot;scss&quot;&gt;&lt;code&gt;position: fixed;
top: 0px;
z-index: 1;
left: 0px;
right: 0px;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Issue 2&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;문제&lt;/code&gt;&lt;br /&gt;스크롤 올리고 내렸을 때 z-index가 높은 상태로 고정된 Header, Footer에 중간 게시물이 잘려서 보인다.&lt;br /&gt;이는 맨 위, 맨 아래에 margin, padding으로 여백을 주어 해결할 수 있다.&lt;br /&gt;중간 게시물을 포함한 container 전체의 위, 아래에 margin을 주는 방식을 택했다.
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;.product__container {
margin-bottom: 74px;
}&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Issue 3&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;문제&lt;/code&gt;&lt;br /&gt;여기서 height는 padding을 포함하지 않은 height로 계산되고, &lt;br /&gt;height: 58px로 주니까 + padding 16px이 되어서 총 높이가 75px이 되어버렸다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1711728089266&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.footer-bar &amp;gt; .footer__icons {
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  padding: 8px 0 8px 0;
  height: 42px;
  background-color: #fff;
  border-top: 1px solid #d9d9d9;
}

.footer-bar &amp;gt; .footer__icons {
    display: flex;
    justify-content: space-evenly;
    align-items: center;
    padding: 8px 0 8px 0;
    height: 58px;
    background-color: #fff;
    border-top: 1px solid #d9d9d9;
    box-sizing: border-box;
}&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;lt;해결 방법&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;box-sizing: border-box; 적용하자!!&lt;br /&gt;&lt;br /&gt;기본 속성은 box-sizing: content; 로, width, height가 content size 기준으로 잡힌다.&lt;br /&gt;즉, padding을 주면 width/height + padding 으로 잡히는 것.&lt;br /&gt;&lt;br /&gt;box-sizing: border-box; 옵션을 주면 width/height = content size + padding 이 된다.&lt;br /&gt;&lt;br /&gt;보통 피그마에서는 box-sizing: border-box; 방식으로 디자인을 많이 해서, &lt;br /&gt;전체에 border-box; 를 적용시켜 놓는 것이 편하다.&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>대외활동/[2024.1학기] KUIT 3기</category>
      <category>CSS</category>
      <category>CSS 이슈</category>
      <category>KUIT</category>
      <category>클론코딩</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/15</guid>
      <comments>https://turtle-hwan.tistory.com/entry/KUIT-3%EA%B8%B0-Web-2%EC%A3%BC%EC%B0%A85-%E5%AE%8C-%EB%8B%B9%EA%B7%BC%EB%A7%88%EC%BC%93-%ED%99%94%EB%A9%B4CSS-%ED%81%B4%EB%A1%A0-%ED%95%98%EA%B8%B0-%EB%B0%8F-%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85#entry15comment</comments>
      <pubDate>Sat, 30 Mar 2024 01:00:37 +0900</pubDate>
    </item>
    <item>
      <title>[KUIT 3기 Web] 2주차(4) - CSS 우선순위, CSS 작명법 BEM(Block Element Modifier), svg 작명법, 추가 내용</title>
      <link>https://turtle-hwan.tistory.com/entry/KUIT-3%EA%B8%B0-Web-2%EC%A3%BC%EC%B0%A84-CSS-%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84-CSS-%EC%9E%91%EB%AA%85%EB%B2%95-BEMBlock-Element-Modifier-svg-%EC%9E%91%EB%AA%85%EB%B2%95-%EC%B6%94%EA%B0%80-%EB%82%B4%EC%9A%A9</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;CSS class name 이름 짓는 법인 BEM 규칙은 이번에 처음 알게 되었다. 지금껏 정해진 className을 쓰면 자동으로 style을 맞춰주는 tailwind, bootstrap 이나 react에서 자동으로 class name을 만들어주는 CSS Module을 자주 써왔어서 접할 기회가 없었던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 svg 작명법까지 찾아서 정리했다.&lt;/p&gt;
&lt;h1&gt;CSS 우선순위&lt;/h1&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;!important( 예시: .title-box{color: red !important;}&lt;/li&gt;
&lt;li&gt;inline(HTML에서 style을 직접 지정했을 때)&lt;/li&gt;
&lt;li&gt;id 선택(#id)&lt;/li&gt;
&lt;li&gt;class명(.class)&lt;/li&gt;
&lt;li&gt;HTML 태그(예시 : h3)&lt;/li&gt;
&lt;li&gt;상위 Element의 속성&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h1&gt;CSS 작명법 BEM(Block Element Modifier)&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CSS 작명법 BEM 이란? &lt;b&gt;Block__Element&amp;mdash;Modifier&lt;/b&gt; 방식으로 class name을 구성하는 것이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Block :
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 element를 묶고 있는 것들&lt;/li&gt;
&lt;li&gt;Block은 재사용 가능한 기능적으로 독립적인 페이지 컴포넌트&lt;/li&gt;
&lt;li&gt;Block은 Block을 감쌀 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Element :
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;큰 block 안에 들어있는 children element&lt;/li&gt;
&lt;li&gt;block을 구성하는 단위이며, 떼어다 다른 곳에 쓸 수 없다&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Modifier : block이나 element의 속성, 조금 다르게 동작하는 것들&lt;code&gt;color-gray&lt;/code&gt;과 &lt;code&gt;theme-normal&lt;/code&gt;가 &lt;b&gt;key-value 타입&lt;/b&gt; 이며, 성질-내용 작성한다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--focused&lt;/code&gt; 된 블럭, &lt;b&gt;불리언(boolean) 타입&lt;/b&gt; 이며, true라고 가정하고 진행한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&amp;lt;BEM, 파일 네이밍 컨벤션의 규칙으로 좋은 사항&amp;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;일반적으로 한 요소는 하이픈으로 연결한다. (예로, input-text, button-submit, modal-alert 등)&lt;/li&gt;
&lt;li&gt;네이밍의 조합은 형태-의미-순서-상태 순으로 사용한다. (예, button-submit-03-disable)&lt;/li&gt;
&lt;li&gt;언더스코어는 파일, 폴더, 이미지 등에만 사용한다. (image_elysia_asset_01.png)&lt;/li&gt;
&lt;li&gt;숫자를 사용할 때는 확장성을 고려해 1, 2 이런 식으로 표현하지 않고 01, 02, 03&amp;hellip; 혹은 001, 002, 003처럼 사용한다. 앞에 0을 붙이지 않으면, 이미지 정렬 시 1 다음에 2가 오지 않고 10이 오는 등, 정렬 순서가 엉망이 될 수 있기 때문이다. (github에서도 1 다음에 10을 정렬하는 듯하다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고 자료&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://nykim.work/15&quot;&gt;https://nykim.work/15&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h1&gt;svg 작명법&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;svg 작명법은 글마다 조금씩 달랐다. 폴더 이름과 구조까지 포함해서 svg를 잘 나눠놓으면 더 효과적일 것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;소문자 사용&lt;/li&gt;
&lt;li&gt;숫자는 처음에 사용하지 말기&lt;/li&gt;
&lt;li&gt;띄어쓰기 사용하지 말기&lt;/li&gt;
&lt;li&gt;축약을 통해 파일명 줄이기 (button -&amp;gt; btn, icon &amp;rarr; icn | ic, background &amp;rarr; bg, image -&amp;gt; img)&lt;/li&gt;
&lt;li&gt;협의된 규칙 사용하기 (현업예시 &amp;rarr; 컴포넌트 유형(접두사) + 이름 + 상태(접미사).png(확장자)&lt;br /&gt;a. ex) btn-pirmary-normal.png / ic-like-hover.png&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고 자료&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://brunch.co.kr/@august9/324&quot;&gt;https://brunch.co.kr/@august9/324&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://spoqa.github.io/2020/03/27/asset-naming.html&quot;&gt;https://spoqa.github.io/2020/03/27/asset-naming.html&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://brunch.co.kr/@pizzakim/26&quot;&gt;https://brunch.co.kr/@pizzakim/26&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h1&gt;추가 내용&lt;/h1&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;reset.css 를 받아서 추가해 두면 각종 태그에 기본으로 달린 속성을 초기화 해준다!!
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;h1, p 태그의 margin 초기화 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;vs code 자동완성 기능
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;div.foo 엔터 치면 class가 foo인 div 생성.&lt;/li&gt;
&lt;li&gt;빈 HTML 파일에 ! 엔터 치면 기본 HTML 생성.&lt;/li&gt;
&lt;li&gt;vscode auto tag 등의 확장프로그램 까는 것도 매우 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;아이콘은 figma에서 svg 바로 추출해서 사용하면 좋다.&lt;/li&gt;
&lt;li&gt;각 크기별 예시 이미지는 &lt;a href=&quot;http://placehold.co/720&quot;&gt;http://placehold.co/720&lt;/a&gt; 이용.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>대외활동/[2024.1학기] KUIT 3기</category>
      <category>bem</category>
      <category>CSS</category>
      <category>KUIT</category>
      <category>SVG</category>
      <category>작명법</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/14</guid>
      <comments>https://turtle-hwan.tistory.com/entry/KUIT-3%EA%B8%B0-Web-2%EC%A3%BC%EC%B0%A84-CSS-%EC%9A%B0%EC%84%A0%EC%88%9C%EC%9C%84-CSS-%EC%9E%91%EB%AA%85%EB%B2%95-BEMBlock-Element-Modifier-svg-%EC%9E%91%EB%AA%85%EB%B2%95-%EC%B6%94%EA%B0%80-%EB%82%B4%EC%9A%A9#entry14comment</comments>
      <pubDate>Sat, 30 Mar 2024 00:39:32 +0900</pubDate>
    </item>
    <item>
      <title>[KUIT 3기 Web] 2주차(3) - CSS positioning, 원하는 위치에 요소 배치하기</title>
      <link>https://turtle-hwan.tistory.com/entry/KUIT-3%EA%B8%B0-Web-2%EC%A3%BC%EC%B0%A83-CSS-positioning-%EC%9B%90%ED%95%98%EB%8A%94-%EC%9C%84%EC%B9%98%EC%97%90-%EC%9A%94%EC%86%8C-%EB%B0%B0%EC%B9%98%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;1) static&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;position 속성의 기본값. 요소를 나열한 순서대로 배치.&lt;/li&gt;
&lt;li&gt;원하는 위치에 콘텐츠를 배치할 방법 없음.&lt;/li&gt;
&lt;li&gt;콘텐츠를 왼쪽에서 오른쪽으로 추가하다가, 오른쪽에 공간이 없을 경우 다음 줄로 넘겨서 순서대로 배치한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) relative&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;static과 같이 나열한 순서대로 배치되지만 top, right, bottom, left 속성을 사용해 원하는 위치를 지정할 수 있다.&lt;/li&gt;
&lt;li&gt;이때 좌표값은 static 기준으로 위치한 곳이 (0px, 0px)이 된다.&lt;/li&gt;
&lt;li&gt;지정한 속성에 따라 상/하/좌/우 원하는 자리에 배치하는 것이 가능 하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3) absolute&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;top, right, bottom, left 속성값을 이용해 요소를 원하는 위치에 배치할 수 있다.&lt;/li&gt;
&lt;li&gt;기준 위치는 position 속성이 relative인 요소 중 가장 가까운 상위 요소.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4) fixed&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 data-ke-size=&quot;size16&quot;&gt;5) sticky&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재 브라우저에 보여지는 화면 기준으로 좌표를 고정해서 표시.&lt;/li&gt;
&lt;li&gt;스크롤 하더라도 같은 위치에 계속 고정되어 있는다.&lt;/li&gt;
&lt;li&gt;부모 요소 기준으로 고정하며, 부모 요소를 넘어가면 고정이 풀린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5-1) sticky가 적용되지 않는 이유&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;부모 요소 안에서만 작동한다.&lt;/li&gt;
&lt;li&gt;부모 요소에 height 속성이 있어야 한다.&lt;/li&gt;
&lt;li&gt;부모 요소에 overflow 속성이 hidden일 경우, sticky 작동 안한다.&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;+) white-space : 단어 기준으로 잘라서 여러 줄로 만들어 준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+) overflow : text가 바깥으로 빠져나왔을 때 보일지, 안 보일지 결정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+) z-index&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;겹치는 박스들의 수직 위치를 조정하기 위한 속성.&lt;/li&gt;
&lt;li&gt;z-index 값이 높을수록 위, 작을수록 아래에 배치되며 -인 경우 기준 콘텐츠의 아래쪽을 의미.&lt;/li&gt;
&lt;li&gt;position 속성이 적용된 경우에만 의미가 있음.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;분명히 z-index는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;position 속성이 적용된 경우에만 의미가 있다라고 기록해 놓고서도 오늘 구현할 때도 까먹어서 왜 z-index 적용이 안 되었나 헤멨다.&amp;nbsp;chrome devtools 들어가서 position 적용해야 한다는 오류 메세지를 보고서야 수정했으니.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;프로젝트를 계속 하면서 느끼는 거지만, CSS 속성들은 큼직큼직한 부분들만 기억하고 있다가 세밀한 조건들은 그때그때 찾아보는 것이 적당하다. 모든 것을 기억하기보단 어떤 상황에서 어떤 검색어로 찾으면 빠를지 딕셔너리처럼 인덱싱 해두면 좋지 않을까.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>대외활동/[2024.1학기] KUIT 3기</category>
      <category>CSS</category>
      <category>KUIT</category>
      <category>position</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/13</guid>
      <comments>https://turtle-hwan.tistory.com/entry/KUIT-3%EA%B8%B0-Web-2%EC%A3%BC%EC%B0%A83-CSS-positioning-%EC%9B%90%ED%95%98%EB%8A%94-%EC%9C%84%EC%B9%98%EC%97%90-%EC%9A%94%EC%86%8C-%EB%B0%B0%EC%B9%98%ED%95%98%EA%B8%B0#entry13comment</comments>
      <pubDate>Sat, 30 Mar 2024 00:03:32 +0900</pubDate>
    </item>
    <item>
      <title>[KUIT 3기 Web] 2주차(2) - CSS grid, grid parent, grid children</title>
      <link>https://turtle-hwan.tistory.com/entry/KUIT-3%EA%B8%B0-Web-2%EC%A3%BC%EC%B0%A82-CSS-grid-grid-parent-grid-children</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;display: grid; 격자 모양으로 보여준다.&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;2000&quot; data-origin-height=&quot;1697&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bAUKq6/btsGcfRbjvh/ql9zP9PDsSDqEwCK1KijzK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bAUKq6/btsGcfRbjvh/ql9zP9PDsSDqEwCK1KijzK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bAUKq6/btsGcfRbjvh/ql9zP9PDsSDqEwCK1KijzK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbAUKq6%2FbtsGcfRbjvh%2Fql9zP9PDsSDqEwCK1KijzK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;509&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1697&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;grid parent 속성과 grid children 속성이 따로 있다.&lt;/li&gt;
&lt;li&gt;grid track : grid의 행 또는 열&lt;/li&gt;
&lt;li&gt;grid cell : grid 한 칸&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Grid parent properties&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;display : inline-grid는 grid에 inline 속성을 부여해 준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;.container {
  display: grid | inline-grid;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;grid-template-rows, grid-template-columns : grid track의 크기를 지정해준다.
&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;1fr 1fr 1fr 은 fraction 약자로, 비율을 의미한다. 1:1:1 비율로 나눠준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;.container {
  grid-template-columns: ...  ...;
  /* e.g. 
  1fr 1fr
  minmax(10px, 1fr) 3fr
  repeat(5, 1fr)
  50px auto 100px 1fr
  */
  grid-template-rows: ... ...;
  /* e.g. 
  min-content 1fr min-content
  100px 1fr max-content
  */
}

.container {
  grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
  grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;repeat : 반복되는 부분이 포함된 경우 repeat()으로 간략하게 반복할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;.container {
    grid-template-columns: repeat(3, 20px [col-start]);
}

repeat(auto-fit, minmax(250px, 1fr));&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;auto-fill, auto-fit은 열, 행 개수를 미리 지정하지 않고 너비가 허용하는 한 최대한 셀을 채운다.&lt;/li&gt;
&lt;li&gt;auto-fill: 가로로 늘렸을 때, 보이지 않는 셀을 만들어 채운다.&lt;/li&gt;
&lt;li&gt;auto-fit: 가로로 늘렸을 때, 각 셀을 늘려서 채운다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;minmax() : 최솟값, 최댓값 범위 내에서 값을 유연하게 처리한다. minmax(min, max) 일 때, min보다 크거나 같고 max보다 작거나 같은 범위.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;.grid-container {
  display: grid;
  /* minmax() 함수 사용법 */
  grid-template-rows: repeat(2, minmax(20px, auto));
  grid-template-columns: minmax(30px, auto) repeat(3, 1fr);
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;grid-template-areas : 다음 그림처럼 각 영역을 지정해서 구분할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;.item-a {
    grid-area: header;
}
.item-b {
    grid-area: main;
}
.item-c {
    grid-area: sidebar;
}
.item-d {
    grid-area: footer;
}
.container {  
    display: grid;  
    grid-template-columns: 50px 50px 50px 50px;  
    grid-template-rows: auto;  
    grid-template-areas:  
    &quot;header header header header&quot;  
    &quot;main main . sidebar&quot;  
    &quot;footer footer footer footer&quot;;  
}&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;2000&quot; data-origin-height=&quot;1408&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dqiHZf/btsGdDqgjL3/5cnzaQLeVfKzqogq1OdSL1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dqiHZf/btsGdDqgjL3/5cnzaQLeVfKzqogq1OdSL1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dqiHZf/btsGdDqgjL3/5cnzaQLeVfKzqogq1OdSL1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdqiHZf%2FbtsGdDqgjL3%2F5cnzaQLeVfKzqogq1OdSL1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;352&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1408&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;grid-template&lt;/li&gt;
&lt;li&gt;row-gap, column-gap, grid-column-gap, grid-row-gap&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1711722603863&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.container {
  /* standard */
  column-gap: &amp;lt;line-size&amp;gt;;
  row-gap: &amp;lt;line-size&amp;gt;;

  /* old */
  grid-column-gap: &amp;lt;line-size&amp;gt;;
  grid-row-gap: &amp;lt;line-size&amp;gt;;
}

.container {
  grid-template-columns: 100px 50px 100px;
  grid-template-rows: 80px auto 80px; 
  column-gap: 10px;
  row-gap: 15px;
}&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;2000&quot; data-origin-height=&quot;1519&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c4sXDf/btsGeb02DF2/f13CnuQkpZJK9v5Z7RyHEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c4sXDf/btsGeb02DF2/f13CnuQkpZJK9v5Z7RyHEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c4sXDf/btsGeb02DF2/f13CnuQkpZJK9v5Z7RyHEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc4sXDf%2FbtsGeb02DF2%2Ff13CnuQkpZJK9v5Z7RyHEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;304&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1519&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;gap, grid-gap : grid 접두사는 오래된 방식으로, 현재는 제거되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1711722665238&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.container {
  /* standard */
  gap: &amp;lt;grid-row-gap&amp;gt; &amp;lt;grid-column-gap&amp;gt;;

  /* old */
  grid-gap: &amp;lt;grid-row-gap&amp;gt; &amp;lt;grid-column-gap&amp;gt;;
}
.container {
  grid-template-columns: 100px 50px 100px;
  grid-template-rows: 80px auto 80px; 
  gap: 15px 10px;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;justify-items, align-items : flex와 동일&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;place-items : &lt;b&gt;&lt;code&gt;&amp;lt;align-items&amp;gt;&lt;/code&gt; / &lt;code&gt;&amp;lt;justify-items&amp;gt;&lt;/code&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;justify-content, align-content : grid 전체 크기가 grid container 크기보다 작을 때 내부에서 grid 자체를 정렬할 수 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;justify-content : 수평 축 방향&lt;/li&gt;
&lt;li&gt;align-content : 수직 축 방향&lt;/li&gt;
&lt;li&gt;place-content : &lt;b&gt;&lt;code&gt;&amp;lt;align-content&amp;gt;&lt;/code&gt; / &lt;code&gt;&amp;lt;justify-content&amp;gt;&lt;/code&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;2000&quot; data-origin-height=&quot;3440&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6i4Qd/btsGfhznu00/kqgg57OyOUlLtrCc2kI34k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6i4Qd/btsGfhznu00/kqgg57OyOUlLtrCc2kI34k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6i4Qd/btsGfhznu00/kqgg57OyOUlLtrCc2kI34k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6i4Qd%2FbtsGfhznu00%2Fkqgg57OyOUlLtrCc2kI34k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;688&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;3440&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://yamoo9.gitbook.io/css-grid/css-grid-guide/grid-implict-auto-track-size&quot;&gt;grid-auto-columns, grid-auto-rows&lt;/a&gt; : 열 크기가 지정되지 않은 라인의 경우, 자동으로 생성되면서 암시적으로 0으로 설정된다. 이 자동 생성 라인 크기를 조정할 때 사용한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;grid-auto-flow&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;.container {
  grid-auto-flow: row | column | row dense | column dense;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;row : 각 행을 차례로 채우고 필요에 따라 새 행을 추가하는 자동 배치&lt;/li&gt;
&lt;li&gt;column : 각 열을 차례로 채우고 필요에 따라 새 열을 추가하는 자동 배치&lt;/li&gt;
&lt;li&gt;dense : 배치 중 나중에 크기가 작은 아이템이 존재할 경우, 그리드 영역 앞부분의 남은 공간에 자동 배치&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고 링크&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://yamoo9.gitbook.io/css-grid/css-grid-guide/minmax-function&quot;&gt;minmax() 함수 | CSS Grid Layout Guidebook&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://css-tricks.com/snippets/css/complete-guide-grid/&quot;&gt;A Complete Guide to CSS Grid | CSS-Tricks&lt;/a&gt;&lt;/p&gt;</description>
      <category>대외활동/[2024.1학기] KUIT 3기</category>
      <category>CSS</category>
      <category>Grid</category>
      <category>KUIT</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/12</guid>
      <comments>https://turtle-hwan.tistory.com/entry/KUIT-3%EA%B8%B0-Web-2%EC%A3%BC%EC%B0%A82-CSS-grid-grid-parent-grid-children#entry12comment</comments>
      <pubDate>Fri, 29 Mar 2024 23:32:58 +0900</pubDate>
    </item>
    <item>
      <title>[KUIT 3기 Web] 2주차(1) - CSS flex box, flex container, flex items</title>
      <link>https://turtle-hwan.tistory.com/entry/KUIT-3%EA%B8%B0-Web-2%EC%A3%BC%EC%B0%A81-CSS-flex-box-flex-container-flex-items</link>
      <description>&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;display : flex;
&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;flex 속성을 해당 element (flex container)에 주면, children elements (flex items)의 위치를 결정한다&lt;/li&gt;
&lt;/ul&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;300&quot; data-origin-height=&quot;119&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5azJ6/btsF7HtcOiK/jiQZuepc7TA2skolP3AV2k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5azJ6/btsF7HtcOiK/jiQZuepc7TA2skolP3AV2k/img.png&quot; data-alt=&quot;flex box 자체를 flex-container라고 부른다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5azJ6/btsF7HtcOiK/jiQZuepc7TA2skolP3AV2k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5azJ6%2FbtsF7HtcOiK%2FjiQZuepc7TA2skolP3AV2k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;119&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;119&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;flex box 자체를 flex-container라고 부른다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;793&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1rmew/btsF9LgM7Za/xKRQiGi3tKjmG4o4F2yarK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1rmew/btsF9LgM7Za/xKRQiGi3tKjmG4o4F2yarK/img.png&quot; data-alt=&quot;flex container 안에 들어있는 element들을 items라 부른다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1rmew/btsF9LgM7Za/xKRQiGi3tKjmG4o4F2yarK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1rmew%2FbtsF9LgM7Za%2FxKRQiGi3tKjmG4o4F2yarK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;793&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;793&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;flex container 안에 들어있는 element들을 items라 부른다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;880&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3ei8t/btsF7TtCdOG/kK8FnrXkxV99vkK7KWmUsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3ei8t/btsF7TtCdOG/kK8FnrXkxV99vkK7KWmUsk/img.png&quot; data-alt=&quot;flex box 용어들&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3ei8t/btsF7TtCdOG/kK8FnrXkxV99vkK7KWmUsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3ei8t%2FbtsF7TtCdOG%2FkK8FnrXkxV99vkK7KWmUsk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;308&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;880&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;flex box 용어들&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;flex container에 주어야 하는 속성과, flex items에 주어야 하는 속성이 따로 있다.&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;2000&quot; data-origin-height=&quot;2000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/s5kZR/btsF65A6Xzt/K8UAwQpwvAplTZnTl2v8fk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/s5kZR/btsF65A6Xzt/K8UAwQpwvAplTZnTl2v8fk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/s5kZR/btsF65A6Xzt/K8UAwQpwvAplTZnTl2v8fk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fs5kZR%2FbtsF65A6Xzt%2FK8UAwQpwvAplTZnTl2v8fk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;300&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;2000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;flex container (parent)의 속성&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;flex-direction : 축의 방향을 결정한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;.container {
  flex-direction: row | row-reverse | column | column-reverse;
}&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;2000&quot; data-origin-height=&quot;920&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clJKOS/btsF9F8KgxY/KbOqPomkOi4PUF3MxfKx61/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clJKOS/btsF9F8KgxY/KbOqPomkOi4PUF3MxfKx61/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clJKOS/btsF9F8KgxY/KbOqPomkOi4PUF3MxfKx61/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclJKOS%2FbtsF9F8KgxY%2FKbOqPomkOi4PUF3MxfKx61%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;138&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;920&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;flex-wrap&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;.container {
  flex-wrap: nowrap | wrap | wrap-reverse;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://codepen.io/team/css-tricks/pen/bEajLE/1ea1ef35d942d0041b0467b4d39888d3&quot;&gt;https://codepen.io/team/css-tricks/pen/bEajLE/1ea1ef35d942d0041b0467b4d39888d3&lt;/a&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;justify-content&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;coq&quot;&gt;&lt;code&gt;.container {
  justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}&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;2000&quot; data-origin-height=&quot;3094&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vD14O/btsF9FgQBgK/X2TBpApbmCctvKiX5UWh3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vD14O/btsF9FgQBgK/X2TBpApbmCctvKiX5UWh3k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vD14O/btsF9FgQBgK/X2TBpApbmCctvKiX5UWh3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvD14O%2FbtsF9FgQBgK%2FX2TBpApbmCctvKiX5UWh3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;300&quot; height=&quot;464&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;3094&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;align-items : cross-axis (y축)을 따라 item들이 배치되는 방식 결정&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;coq&quot;&gt;&lt;code&gt;.container {
    align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;align-content : flex-wrap이 설정된 여러 줄의 flex-container에만 적용된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;coq&quot;&gt;&lt;code&gt;.container {
    align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;gap, row-gap, column-gap : item 간의 간격을 직접 지정할 수 있다. flex, grid, multi-column layout 모두에서 작동한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;scss&quot;&gt;&lt;code&gt;.container {
    display: flex;
    ...
    gap: 10px;
    gap: 10px 20px; /* row-gap column gap */
    row-gap: 10px;
    column-gap: 20px;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;flex items (children)의 속성&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;order : 기본적으로 flex items 는 HTML 코드 순서대로 배치되지만, order 속성으로 순서를 따로 제어할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;.item {
  order: 5; /* default is 0 */
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;flex-grow : flex item이 얼마만큼의 비율로 공간을 차지할지 결정한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자신의 flex-grow 숫자 / items flex-grow 총합 만큼의 비율을 차지한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;.item {
  flex-grow: 4; /* default 0 */
  /* Negative numbers are invalid. */
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;flex-shrink : 바깥으로 빠져나간 부분에 대해서 얼마만큼의 비율로 줄여줄지 결정한다.&lt;/li&gt;
&lt;li&gt;flex-basis : flex 아이템 기본 크기를 설정 &amp;ne; width
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;width 속성과 flex-basis 속성이 함께 있을 때 조심하자!&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.item {
flex-basis: auto /* default */
or &amp;lt;width&amp;gt;
}&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;flex-grow, flex-shrink, flex-basis 속성 한 번에 주기&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;dts&quot;&gt;&lt;code&gt;.item {
  flex: 0 1 auto /* default */
    or &amp;lt;flex-grow&amp;gt; &amp;lt;flex-shrink&amp;gt; &amp;lt;flex-basis&amp;gt;
    or &amp;lt;flex-grow&amp;gt;
    or &amp;lt;flex-basis&amp;gt;
    or &amp;lt;flex-grow&amp;gt; &amp;lt;flex-basis&amp;gt;
    or &amp;lt;flex-grow&amp;gt; &amp;lt;flex-shrink&amp;gt;
}
/* flex-grow, flex-shrink는 숫자만 적는 UNITLESS value
* flex-basis는 단위가 포함된 UNIT value */&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;align-self : 개별 flex item한테만 align-items를 제정의할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;coq&quot;&gt;&lt;code&gt;.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고자료&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://css-tricks.com/snippets/css/a-guide-to-flexbox/#aa-flexbox-tricks&quot;&gt;A Complete Guide to Flexbox | CSS-Tricks&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://www.samanthaming.com/flexbox30/&quot;&gt;Flexbox30 | SamanthaMing.com&lt;/a&gt;&lt;/p&gt;</description>
      <category>대외활동/[2024.1학기] KUIT 3기</category>
      <category>CSS</category>
      <category>Flex</category>
      <category>KUIT</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/11</guid>
      <comments>https://turtle-hwan.tistory.com/entry/KUIT-3%EA%B8%B0-Web-2%EC%A3%BC%EC%B0%A81-CSS-flex-box-flex-container-flex-items#entry11comment</comments>
      <pubDate>Wed, 27 Mar 2024 23:36:44 +0900</pubDate>
    </item>
    <item>
      <title>[Git / Github] git submodule pull 받아오는 방법 및 용도</title>
      <link>https://turtle-hwan.tistory.com/entry/Git-Github-git-submodule-pull-%EB%B0%9B%EC%95%84%EC%98%A4%EB%8A%94-%EB%B0%A9%EB%B2%95-%EB%B0%8F-%EC%9A%A9%EB%8F%84</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;git_submodule.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blnTmS/btsITP9Tk7x/KPR1CXifnm1hcaBBKbomxK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blnTmS/btsITP9Tk7x/KPR1CXifnm1hcaBBKbomxK/img.png&quot; data-alt=&quot;git submodule&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blnTmS/btsITP9Tk7x/KPR1CXifnm1hcaBBKbomxK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblnTmS%2FbtsITP9Tk7x%2FKPR1CXifnm1hcaBBKbomxK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;768&quot; data-filename=&quot;git_submodule.png&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;git submodule&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h1&gt;git submodule 사용 계기&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 ithome 프로젝트를 Next.js + TS 로 마이그레이션 하면서 git submodule 기능을 사용했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 하나의 repository에 프론트, 백이 폴더로 구분되어 같이 들어 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트만 환경을 Next.js로 바꾸면서 프론트 repo를 따로 만들었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;localhost에서 테스트할 때 편의성을 위해 백 repo를 포함시킬 필요가 있어서 submodule로 포함시켰다.&lt;/p&gt;
&lt;pre class=&quot;haml&quot;&gt;&lt;code&gt;## 기존 구조
ithome
---/frontend (React)
---/backend  (Nest.js)
---docker-compose.yaml

## 새로운 구조
ithome-front (Next.js 메인)
---/backend @ 8d972c3 (submodule)
---/public
---/src
---/src/@core
---/src/@shared
---/src/@store
---/src/@type
---/src/app (app router)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;submodule로 포함하면 독립된 git 저장소를 가져올 수 있으며 commit부터 저장소 자체를 별개로 관리할 수 있는 이점이 있다. 일종의 바로가기와 비슷하다고 보면 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://git-scm.com/book/ko/v2/Git-%EB%8F%84%EA%B5%AC-%EC%84%9C%EB%B8%8C%EB%AA%A8%EB%93%88&quot;&gt;Git 공식 문서 - 서브모듈&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1711338102280&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;Git - 서브모듈&quot; data-og-description=&quot;gitmodules 파일에 있는 URL은 조건에 맞는 사람이면 누구든지 Clone 하고 Fetch 할 수 있도록 접근할 수 있어야 한다. 예를 들어 다른 사람이 Pull을 하는 URL과 라이브러리의 작업을 Push 하는 URL이 서로 &quot; data-og-host=&quot;git-scm.com&quot; data-og-source-url=&quot;https://git-scm.com/book/ko/v2/Git-%EB%8F%84%EA%B5%AC-%EC%84%9C%EB%B8%8C%EB%AA%A8%EB%93%88&quot; data-og-url=&quot;https://git-scm.com/book/ko/v2/Git-%EB%8F%84%EA%B5%AC-%EC%84%9C%EB%B8%8C%EB%AA%A8%EB%93%88&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://git-scm.com/book/ko/v2/Git-%EB%8F%84%EA%B5%AC-%EC%84%9C%EB%B8%8C%EB%AA%A8%EB%93%88&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://git-scm.com/book/ko/v2/Git-%EB%8F%84%EA%B5%AC-%EC%84%9C%EB%B8%8C%EB%AA%A8%EB%93%88&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;Git - 서브모듈&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;gitmodules 파일에 있는 URL은 조건에 맞는 사람이면 누구든지 Clone 하고 Fetch 할 수 있도록 접근할 수 있어야 한다. 예를 들어 다른 사람이 Pull을 하는 URL과 라이브러리의 작업을 Push 하는 URL이 서로&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;git-scm.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;submodule이 포함된 저장소 clone 시 submodule 받아오는 방법&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;submodule이 포함된 git 저장소를 쓸 때, clone 이후 받는 방식과 clone 시 한 번에 받는 방식이 있다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;git clone 이후 따로 받는 법&lt;/h2&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;## submodule이 있는 폴더로 이동한다.

git submodule init 
### 해당 명령어로 git submodule을 초기화 해줘야 그 안에서 pull을 할 수 있다.  
### 이걸 해줘야 submodule 별도의 git remote가 연결되는 것 같다.

git submodule update # submodule pull 가져오는 명령어
git submodule update --remote&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;git clone과 동시에 받는 법&lt;/h2&gt;
&lt;pre class=&quot;crmsh&quot;&gt;&lt;code&gt;git clone --recurse-submodules &amp;lt;https://github.com/~&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로 clone 받는 개념이라 .env 파일 다시 받아줘야 하며, npm i도 따로 해줘야 한다&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;git clone 이후 init, update 한 번에 하기&lt;/h2&gt;
&lt;pre class=&quot;mipsasm&quot;&gt;&lt;code&gt;git submodule update --init #이 명령으로 init과 update 한 번에 가능하다.
git submodule update --init &amp;lt;submodule 경로&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;submodule 만드는 법&lt;/h1&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;git submodule add &amp;lt;private repository 주소&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 명령어를 입력하면, 루트 디렉토리에 .gitmodule 파일이 생기고, 그 안에는 폴더명과 remote url이 담겨있다&lt;/p&gt;
&lt;pre class=&quot;awk&quot;&gt;&lt;code&gt;# .gitmodule 파일 예시
[submodule &quot;backend&quot;]
    path = backend
    url = &amp;lt;https://github.com/Sublet-K/Sublet.git&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;&amp;nbsp;&lt;/h1&gt;
&lt;h1&gt;submodule의 여러 사용법&lt;/h1&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;submodule로 백엔드, 프론트 등 별개의 repository를 연결하는 것 외에도 .env 환경변수, 000.pem 등 노출되면 안 되는 파일 관리에도 사용할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트가 커질수록 팀원별로 동일하게 관리하기가 아주 힘들어지는 .env 파일들을 모은 private repo를 하나 만들고, 이걸 submodule로 연결시켜주는 방식이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참고 자료&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java11 + Spring boot 환경에서 application.yml 파일 git submodule로 관리하기 : &lt;a href=&quot;https://percyfrank.github.io/infra/Infra01/#5-github-actions-cicd-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8&quot;&gt;https://percyfrank.github.io/infra/Infra01/#5-github-actions-cicd-스크립트&lt;/a&gt;&lt;/p&gt;</description>
      <category>프로그래밍</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/9</guid>
      <comments>https://turtle-hwan.tistory.com/entry/Git-Github-git-submodule-pull-%EB%B0%9B%EC%95%84%EC%98%A4%EB%8A%94-%EB%B0%A9%EB%B2%95-%EB%B0%8F-%EC%9A%A9%EB%8F%84#entry9comment</comments>
      <pubDate>Mon, 25 Mar 2024 12:41:07 +0900</pubDate>
    </item>
    <item>
      <title>[ithome / TIL - 240324]  Next.js + TypeScript로 마이그레이션</title>
      <link>https://turtle-hwan.tistory.com/entry/ithome-TIL-240324-Nextjs-TypeScript%EB%A1%9C-%EB%A7%88%EC%9D%B4%EA%B7%B8%EB%A0%88%EC%9D%B4%EC%85%98</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://github.com/Sublet-K/ItHome-Front/pull/11&quot;&gt;PR11&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;기존 React + JS로 개발했던 ithome 프로젝트의 Next.js + TypeScript로 마이그레이션&lt;/h1&gt;
&lt;h3&gt;Next.js와 타입스크립트로 마이그레이션을 결정한 이유 =&amp;gt; [링크 추가 예정]&lt;/h3&gt;
&lt;p&gt;그 중 이번주 까지 끝내야 할 내가 맡았던 페이지들을 Next.js + TS 환경으로 마이그레이션 하면서 겪은 것들이다.&lt;/p&gt;
&lt;h2&gt;0. 먼저 Map.js / SearchSubletInfo.js 파일을 .tsx 파일로 바꾸기.&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;- eslint와 vscode 오류 잡아가는 방식으로 진행. 대부분 해당하는 ts type 추가 
    =&amp;gt; marker 나 naver.map 관련해서 type을 도무지 알 수 없는 것이 있어 임시방편으로 any를 썼는데 나중에 더 자세히 알아보고 수정해야겠다.
- 기존 React useEffect 내에서 fetch하는 코드를 그대로 가져왔더니 이를 쓰기 위해서 &amp;quot;use client&amp;quot;를 파일 최상위에 추가하라는 error가 떴다.&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;이전에 썼던 Next.js 12 버전에서는 안 그랬던 것 같아 찾아보니, &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Next 12에서는 기본적으로 CSR로 동작하고 getServerSideProps()를 사용해서 명시적으로 SSR을 적용해 줘야 했었다.&lt;/li&gt;
&lt;li&gt;Next 14에서는 &lt;a href=&quot;https://stackoverflow.com/questions/75119545/is-possible-to-use-getserversideprops-on-client-components-inside-app-dir&quot;&gt;(아마도 13부터는)&lt;/a&gt; 기본적으로 모든 페이지가 SSR로 동작하고, 명시적으로 파일 최상위에 &amp;quot;use client&amp;quot;를 추가하면 해당 페이지는 CSR로 동작하는 것으로 이해했다.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nextjs.org/docs/app/api-reference/functions/fetch&quot;&gt;공식 docs : Next에서 확장된 fetch 사용법&lt;/a&gt; &lt;ul&gt;
&lt;li&gt;SSR을 위해 마이그레이션 중인데 &amp;quot;use client&amp;quot;를 무작정 추가하면 의미 없는 것 같아 이런저런 방법을 고민하면서 가능한 SSR 페이지를 늘려가야겠다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next.js가 2년도 안 된 거 같은데 12 -&amp;gt; 14로 버전업 하면서 짧은 시간 동안 많은 변화가 있었다. 구글링 해도 각 버전에 알맞게 원하는 정보를 바로 찾기가 까다롭다. 결국 공식 문서로 회귀하게 된다... Next.js 공식 문서가 잘 관리되고 있어서 정말 다행이지..&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이전 프로젝트 정리 =&amp;gt; [링크 추가]&lt;/li&gt;
&lt;li&gt;CSR, SSR 차이 =&amp;gt; [링크 추가]&lt;/li&gt;
&lt;li&gt;Next.js 14에서 SSR fetch 방식, &amp;quot;use client&amp;quot; 명령어의 의미 정리 =&amp;gt; [링크 추가]&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1. url 대문자 인식 안되는 오류 발생 =&amp;gt; 모든 app router 경로 소문자로 수정!!&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;분명 url 경로는 대소문자 상관없는 것으로 알고 있었는데 Next app router 방식을 도입하면서, 특정 URL에 접속하면 /not-found으로 뜨면서 404 오류가 발생했다.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/63695742/redirect-in-next-js-from-uppercase-to-lowercase-url&quot;&gt;소문자로 바꾸니 해결&lt;/a&gt;되어서 전부 변경했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 백엔드 / mongodb docker 켜서 프론트와 연결하는 법 복기.. (&lt;del&gt;기억력의 문제로&lt;/del&gt;)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;항상 오류 기록을 남기려고 노력하는 탓에 기록은 여기저기 흩뿌려져 있는데 그걸 못 찾아서 문제다..&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-Shell&quot;&gt;# docker compose up -d mongo 
    # backend만 npm run start으로 따로 키려면 backend 안의 .env에서 mongo:27017 부분이 localhost:27017 로 바뀌어야 함!!
    # mongo db를 안 키고 mongo atlas로 사용하려면 DB_URL env를 atlas 것으로 바꿔주어야 함!!
# docker compose up -d mongo backend    =&amp;gt; 일반적인 db, back 둘 다 켜고 테스트 시
# docker compose up -d --build backend     =&amp;gt; backend 파일 변경 후 재빌드 필요할 때 &lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. localhost 서버에서 ssl 인증 받아서 https로 실행할 때, ERR_CERT_AUTHORITY_INVALID 문제&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;이유는 모르겠는데 예전에 받아둔 key.pem / cert.pem 을 백엔드 서버와 프론트 서버를 동일한 파일로 맞추니까 해결 됨!&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&quot;https://mungkhs1.tistory.com/64&quot;&gt;ssl localhost에서 인증서 발급 참고 사이트&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ssl 원리 및 localhost ssl 인증 원리 정리 필요,.. =&amp;gt; [링크 추가]&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. next.js 12 등 이전 버전의 pages/_app.js 및 pages/_document.js는 app/layout.js 루트 레이아웃 하나로 대체된 관계로, meta tag 및 html head tag들은 app/layout.js 파일에서 작업!&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;기본 html 파일이 app/layout.js 하나로 통합되었다.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/XionWCFM/Nextjs-docs-Korean-translation/blob/main/nextjsdocs/BuildingYourApplication/Upgrading/App_Router_Migration.md&quot;&gt;next.js 14 업데이트 관련 참고 글 - app router, _document.js 등&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5. global.css 로 이상하게 화면에 보이는 것 주석처리!&lt;/h3&gt;</description>
      <category>TIL (Today I Learned)</category>
      <category>ithome</category>
      <category>next.js</category>
      <category>Next.js 14</category>
      <category>Til</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/8</guid>
      <comments>https://turtle-hwan.tistory.com/entry/ithome-TIL-240324-Nextjs-TypeScript%EB%A1%9C-%EB%A7%88%EC%9D%B4%EA%B7%B8%EB%A0%88%EC%9D%B4%EC%85%98#entry8comment</comments>
      <pubDate>Mon, 25 Mar 2024 00:33:44 +0900</pubDate>
    </item>
    <item>
      <title>[KUIT 3기 Web] 1주차 - Web 기본 지식</title>
      <link>https://turtle-hwan.tistory.com/entry/1%EC%A3%BC%EC%B0%A8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Web 기본 지식들을 키워드 기반으로 정리해보았다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HTML, CSS, JS&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;HTML : 페이지의 틀&lt;/li&gt;
&lt;li&gt;JS : HTML element 간의 동적인 동작&lt;/li&gt;
&lt;li&gt;CSS : 색깔, element 배치 등 디자인 요소&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Web API&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTML5는 2004년에 등장했고 2014년에 W3C에서 표준안을 확정했으며, 다양한 Web APIs를 제공한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTML Geolocation API&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자(브라우저)의 현재 위치를 받아올 수 있다. 지도 현 위치 표시 기능에 사용한다. 단, 브라우저 차원에서 보안 문젤 https에서만 사용 가능하도록 제한이 걸린 상태이다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTML Drag and Drop API&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 페이지에서 JS를 이용해서 element의 드래그, 드롭, 이동, 삭제를 간편히 구현 가능하게 지원한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTML Web Storage API&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;브라우저에서 session, local storage를 제공한다. 브라우저 프로세스가 종료되기 전까지 데이터를 저장 가능하다. 쿠키보다 더 큰 양의 데이터 저장 가능하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTML Web Workers API&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래 싱글스레드인 JS를 멀티스레드처럼 사용할 수 있게 해준다. 웹 앱의 백그라운드에서 병렬 작업 처리가 가능하다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTML SSE(Server-Sent Events) API&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;chatGPT에 사용된다. 서버에서 클라이언트로 단방향 메세지 보낼 수 있다. HTTP 통신으로 서버에서 실시간 업데이트 받을 수 있고, 실시간 데이터 스트리밍이나 푸시 알림 구현 시 사용한다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;HTML(HyperText Markup Language) 기본구조&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;XML 문법에서 출발하여, 태그 기반으로 이루어진다.)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;html&amp;gt;&amp;lt;/html&amp;gt;&lt;/code&gt; : 문서의 루트 요소를 정의하고, 전체 문서 범위를 알려준다.&lt;/li&gt;
&lt;li&gt;head : 눈에 보이지 않는 요소 / SEO에 필요한 요소 / 웹 페이지의 주요 정보를 담고 있다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;meta&amp;gt;, &amp;lt;link&amp;gt;, &amp;lt;script&amp;gt;, &amp;lt;title&amp;gt;&lt;/code&gt; 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;body : 일반적으로 페이지에 보이는 element들이 들어가는 위치&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.w3schools.com/html/html5_semantic_elements.asp&quot;&gt;Sementic tag&lt;/a&gt; : HTML5에서 &lt;code&gt;&amp;lt;section&amp;gt;, &amp;lt;header&amp;gt;, &amp;lt;nav&amp;gt;, &amp;lt;footer&amp;gt;&lt;/code&gt; 등 기능은 없지만 추가적인 의미를 쉽고 빠르게 알려줄 수 있는 시멘틱 태그가 추가되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;metadata&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;charset=&amp;rdquo;UTF-8&amp;rdquo; : 문서 인코딩 속성&lt;/li&gt;
&lt;li&gt;name=&amp;rdquo;viewport&amp;rdquo; : PC/mobild 기기에 따른 너비 및 초기 화면 비율&lt;/li&gt;
&lt;li&gt;name=&amp;rdquo;keywords&amp;rdquo; : 키워드&lt;/li&gt;
&lt;li&gt;name=&amp;rdquo;description&amp;rdquo; : 페이지 설명 (검색엔진에 간략히 띄워지는 부분)&lt;/li&gt;
&lt;li&gt;name=&amp;rdquo;author&amp;rdquo; : 작가&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag?hl=ko&quot;&gt;name=&amp;rdquo;robots&amp;rdquo;&lt;/a&gt; : 구글 등의 검색엔진 봇에 자세한 행동양식을 지정할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;HTML Box-model : margin, border, padding, content가 포함된 element model&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;box의 width, height를 border size까지 포함시키고 싶다면 box-sizing : borer-box 속성을 주어야 한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;margin collapsing&lt;/b&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;인접한 형제 요소들의 margin-top과 margin-bottom이 합쳐진다.&lt;/li&gt;
&lt;li&gt;상위 요소의 margin-top과 첫 번째 자식 요소의 margin-top이 합쳐진다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;display : CSS의 속성 중 하나로 element의 표시 방법 지정한다.&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;block : element가 새로운 줄에서 시작하고, 가능한 최대 width를 가진다.&lt;/li&gt;
&lt;li&gt;inline : element가 새로운 줄에서 시작하지 않고, content의 일부로 간주된다.&lt;/li&gt;
&lt;li&gt;inline-block : inline과 block의 특성을 모두 갖고 있고, element가 새로운 줄에서 시작하지 않으면서도 width를 지정할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;SEO (Search Engine Optimizer)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SEO를 잘 고려할수록 검색엔진의 크롤러 봇이 웹페이지 내용을 자세히 긁어가서 더 많은 사람들에게 노출시킬 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;SPA (single page application)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 페이지를 이동하더라도 최초에 전송받은 하나의 HTML 안에서 컴포넌트만 교체된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;CSR (Client-Side Rendering)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;React는 기본적으로 CSR 방식을 따르며, SSR로 작동시키려면 추가 구현이 필요하다.&lt;/li&gt;
&lt;li&gt;CSR은 사용자가 브라우저에 페이지를 띄우면, HTML (header는 받아오지만, body는
&lt;div id=&quot;&amp;rdquo;root&amp;rdquo;&quot;&gt;&amp;nbsp;&lt;/div&gt;
이렇게만 띄워진 상태에서 javascript 엔진에 의해 js 파일들이 실행되어 컴포넌트가 만들어지고, 렌더링된다.&lt;/li&gt;
&lt;li&gt;미리 모든 페이지에서 필요한 js 파일들 받아두고, 다른 페이지 이동 시 해당 페이지에 필요한 js를 실행해 새로운 컴포넌트를 렌더링하고 화면 업데이트 한다.&lt;/li&gt;
&lt;li&gt;CSR에서는 프론트 서버가 먼저 브라우저에 HTML 틀과 JS 파일들을 전송하고, 브라우저가 백 서버와 통신하면서 데이터를 받아서 브라우저 화면에 뿌려준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;장점&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;short TTI(Time To Interact) : SSR보다 빠른 interaction&lt;/li&gt;
&lt;li&gt;Lazy loading : 필요한 시점에 데이터를 로딩한다.&lt;br /&gt;ex) 스크롤을 내리기 전까지 페이지에 보이지 않는 부분은 로딩하지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;단점&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SEO에 약하다. : 요청이 전달되기 전까지 body가 비어있다.&lt;/li&gt;
&lt;li&gt;long TTV(Time To View) : 초기 로딩이 오래 걸린다&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img style=&quot;letter-spacing: 0px;&quot; src=&quot;https://blog.kakaocdn.net/dn/byF0Lw/btsF2vSURZE/ZVprGqsbB0GsyyJp0qqGwk/img.png&quot; width=&quot;658&quot; height=&quot;464&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;2000&quot; data-origin-height=&quot;1411&quot; data-filename=&quot;1_csr.png&quot; /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;SSR (Server-Side Rendering)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Next.js에 SSR 기능이 포함되어 있다.&lt;/li&gt;
&lt;li&gt;각 페이지 URL에 따라 보여줄 내용(HTML body 부분)이 결정되어 있다.&lt;/li&gt;
&lt;li&gt;서버(프론트 서버)는 URL을 기준으로 HTML을 만들어서 브라우저에 전송하며, 추가 js 파일 등의 리소스도 포함 가능하다.&lt;/li&gt;
&lt;li&gt;SSR에서는 프론트 서버가 백 서버의 데이터를 다 모은 다음에 HTML로 어느 정도 생성한 후에 브라우저에 뿌려준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;장점&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;short TTV(Time To View) : 초기 페이지 로딩이 빠르다.&lt;/li&gt;
&lt;li&gt;SEO에 좋다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;lt;단점&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;long TTI(Time To Interact)&lt;/li&gt;
&lt;li&gt;프론트 서버 연산량이 늘어나 서버 과부화 발생 가능성&lt;/li&gt;
&lt;li&gt;페이지 이동 시 새로 rendering 하게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;913&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgJsRS/btsF0IF1UGp/rykEJebzr96plsbdxPN1m0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgJsRS/btsF0IF1UGp/rykEJebzr96plsbdxPN1m0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgJsRS/btsF0IF1UGp/rykEJebzr96plsbdxPN1m0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgJsRS%2FbtsF0IF1UGp%2FrykEJebzr96plsbdxPN1m0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;658&quot; height=&quot;469&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;913&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;참고 글&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://yozm.wishket.com/magazine/detail/2330/&quot;&gt;https://yozm.wishket.com/magazine/detail/2330/&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=iZ9csAfU5Os&quot;&gt;https://www.youtube.com/watch?v=iZ9csAfU5Os&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=YuqB8D6eCKE&quot;&gt;https://www.youtube.com/watch?v=YuqB8D6eCKE&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://80000coding.oopy.io/fde38c6f-e65d-4c1a-af45-176abee40389&quot;&gt;https://80000coding.oopy.io/fde38c6f-e65d-4c1a-af45-176abee40389&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://evan-moon.github.io/2018/09/25/universal-ssr/&quot;&gt;https://evan-moon.github.io/2018/09/25/universal-ssr/&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;script&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;script 태그를 head에 두는 경우 : html 문서는 위에서 아래로 파싱된다. script가 다운로드되고, 로딩 및 실행되는 동안 파싱이 중단되므로 사용자 입장에서는 웹이 느리게 띄워지는 것처럼 보이거나, JS에서 DOM element를 찾지 못하는 경우가 발생한다!!&lt;/li&gt;
&lt;li&gt;script 태그를 body 하단에 두는 경우 : HTML이 모두 파싱되고 script가 다운로드 되나, 관리의 어려움과 속도 느린 문제점.&lt;/li&gt;
&lt;li&gt;DOM을 따라 순서대로 실행되어야 할 때.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;defer&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;script defer src=&quot;index.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DOM이나 다른 스크립트에 의존성이 있고, script 간의 실행 순서가 중요한 경우.&lt;br /&gt;defer 속성을 추가하면 HTML 파싱과 동시에 script 다운로드가 백그라운드에서 이루어지며, HTML 파싱이 끝난 후에 script가 실행되도록 보장된다.&lt;br /&gt;여러 개의 script에 defer 속성이 걸려있다면, 위에서부터 순서대로 실행 되는 것이 보장된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;async&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;&amp;lt;script async src=&quot;index.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DOM이나 다른 스크립트에 의존성이 없고, script 간의 실행 순서가 중요하지 않은 경우.&lt;br /&gt;async 속성을 추가하면 script가 HTML 파싱과 동시에 비동기적으로 백그라운드에서 다운로드된다.&lt;br /&gt;단, script 실행은 script 다운로드가 먼저 끝나는 순서대로 실행되며, script 실행 중에는 HTML 파싱이 중단된다. 따라서 script 실행 순서를 보장할 수 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;참고&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://velog.io/@ank0425/JavaScript-%EC%8B%A4%ED%96%89%EB%90%98%EB%A9%B4-html-%ED%8C%8C%EC%8B%B1-%EC%A4%91%EB%8B%A8%EB%90%98%EB%8A%94-%EC%9D%B4%EC%9C%A0%EC%97%90-%EB%8C%80%ED%95%B4&quot;&gt;https://velog.io/@ank0425/JavaScript-실행되면-html-파싱-중단되는-이유에-대해&lt;/a&gt;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;웹사이트 제작 시 고려사항&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;웹 표준 : 웹사이트 작성 시 따르면 좋은 공식 표준, 기술 규격 (World Wide Web Consortium)&lt;/li&gt;
&lt;li&gt;웹 접근성 : 장애 여부와 상관없이 웹사이트를 이용 가능하도록 하는 방식. 스크린 리더기를 사용할 때 인식 가능하도록 &lt;img /&gt; 태그의 alt 속성 넣는다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;웹 콘텐츠 접근성 규칙 (WCAG 3, W3C Accessibility Guidelines)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;크로스 브라우징 : 모든 브라우저, 기기에서 사이트가 제대로 접근하도록 개발하는 것.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;caniuse.com&lt;/li&gt;
&lt;li&gt;Vender Prefix (벤더 프리픽스) : 특정 브라우저 제조사의 접두사를 css 속성 앞에 추가하는 것. 특정 브라우저에서만 제공하는 속성을 사용할 때 필요하다. (ex. chrome의 -webkit-, IE의 -ms- 등)&lt;/li&gt;
&lt;li&gt;Prefix Free 라이브러리도 있어서, 자동으로 벤더 프리픽스 적용해주는 기능도 존재한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>대외활동/[2024.1학기] KUIT 3기</category>
      <category>HTML</category>
      <category>javascript</category>
      <category>KUIT</category>
      <category>seo</category>
      <category>Web API</category>
      <author>Turtle-hwan</author>
      <guid isPermaLink="true">https://turtle-hwan.tistory.com/5</guid>
      <comments>https://turtle-hwan.tistory.com/entry/1%EC%A3%BC%EC%B0%A8#entry5comment</comments>
      <pubDate>Tue, 19 Mar 2024 08:00:37 +0900</pubDate>
    </item>
  </channel>
</rss>