<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>판수개발자</title>
    <link>https://sjoongh.tistory.com/</link>
    <description>이상과 현실사이에서 균형을 잡고싶은 Backend 개발자입니다.            sjh87355@gmail.com</description>
    <language>ko</language>
    <pubDate>Thu, 2 Jul 2026 20:30:11 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>sjoongh</managingEditor>
    <image>
      <title>판수개발자</title>
      <url>https://tistory1.daumcdn.net/tistory/5158658/attach/8604d7bc68054f93baac762a5a486e98</url>
      <link>https://sjoongh.tistory.com</link>
    </image>
    <item>
      <title>2025 개발자 회고</title>
      <link>https://sjoongh.tistory.com/entry/2025-%EA%B0%9C%EB%B0%9C%EC%9E%90-%ED%9A%8C%EA%B3%A0</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;2025.01&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2025년의 1월달은 바쁘게 보냈었다. 이미 2024년 12월부터 구글 클라우드 ai 교육과 토스러너스하이를 동시에 진행해서 그런것 같다. 지나고보니 배운것도 많았고 재미었던것같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;구글클라우드교육&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글 클라우드 교육을 신청한 이유는 AI를 조금이나마 더 알아가고 싶어서 신청했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 흔히 사용하는 기계들의 동작원리를 몰라도 사용하는것에는 전혀 불편함이 없지만 AI는 흔히 사용하는 도구 이상의 가치가 있다고 생각해 이 녀석이 어떻게 동작하는지 나는 어떤식으로 사용해야할지? 등 AI에 대한 대략적인 큰 그림을 그려보고 싶었고 이를 통해 조금이나마 더 폭 넓게 활용하고 싶었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교육은 생각보다 유익하고 재미있었고 과제도 수행하며 빠르게 시간을 보낼 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image (1).png&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;432&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ta3xZ/dJMcafLWUkP/2YgmjMT7KeXjzuKBwtKrnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ta3xZ/dJMcafLWUkP/2YgmjMT7KeXjzuKBwtKrnk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ta3xZ/dJMcafLWUkP/2YgmjMT7KeXjzuKBwtKrnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fta3xZ%2FdJMcafLWUkP%2F2YgmjMT7KeXjzuKBwtKrnk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;356&quot; height=&quot;432&quot; data-filename=&quot;image (1).png&quot; data-origin-width=&quot;356&quot; data-origin-height=&quot;432&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교육을 수료하면 하면 이런식으로 뱃지도 주기에 성취감이 있었다&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멘토분이 생각하는 개발자의 가치관에 얘기를 들을 수 있었고 회사를 재직하고 있는 개발자가 본인이 속해있는 팀과 업무에서 어떠한 기여를 할 수 있고 어떤 이득을 가져다줄 수 있는지와 같이 한달 간 주도적으로 성장해 나갈 수 있는지와 같이 더 높은 성장을 위해 달려나갈 수 있는 작은 발판을 주는 프로그램이었다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;마침 글또분들중에서도 러너스하이를 진행하시는 분들이 있어 함께하실 분들을 모집해 정보도 공유하고 서로 어떤 목표를 세우고 달려나갈지에 대한 대화도 많이 했었다,(무려 23분이나!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Caf9b/dJMcabQjy3l/fJk6KcvLMG9QKForm35hM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Caf9b/dJMcabQjy3l/fJk6KcvLMG9QKForm35hM1/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;379&quot; data-origin-height=&quot;432&quot; data-filename=&quot;image (2).png&quot; style=&quot;width: 52.4051%; margin-right: 10px;&quot; data-widthpercent=&quot;53.02&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Caf9b/dJMcabQjy3l/fJk6KcvLMG9QKForm35hM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCaf9b%2FdJMcabQjy3l%2FfJk6KcvLMG9QKForm35hM1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;379&quot; height=&quot;432&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/A550f/dJMcaaKDLyD/7mmtrzVy9uJDTMEwat9OVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/A550f/dJMcaaKDLyD/7mmtrzVy9uJDTMEwat9OVK/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;754&quot; data-origin-height=&quot;970&quot; data-filename=&quot;image (3).png&quot; width=&quot;415&quot; height=&quot;534&quot; style=&quot;width: 46.4321%;&quot; data-widthpercent=&quot;46.98&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/A550f/dJMcaaKDLyD/7mmtrzVy9uJDTMEwat9OVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FA550f%2FdJMcaaKDLyD%2F7mmtrzVy9uJDTMEwat9OVK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;754&quot; height=&quot;970&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;li&gt;Kafka 기반 DLQ 적용&lt;/li&gt;
&lt;li&gt;SAGA 패턴을 통한 분산 트랜잭션 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1) 무중단 배포&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리 서비스는 B2B였기에 일반적으로 고객 이용시간 외에 배포를 진행했지만, 간혹 운영시간 중 급하게 배포해야 하는 상황이 있었다. 다행히 지금까지는 파드 재시작 시간이 짧아서 문제가 없었지만, 시스템이 커질수록 안정적인 배포 방식이 필요하다고 판단해 적용시켰다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 돈과 관련된 문제가 발생하는건 가장 핵심 이슈라고 생각해 주문 도메인에서 에러가 발생할 경우 즉각적으로 알림이 오면 좋겠다고 생각했다. 우리팀은 기존에 Grafana Loki를 잘 사용하고 있었고 이를 기반으로 슬랙을 통해 알림이 오도록 구성했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀 내부적으로는 에러코드 관리가 잘되고 있었기에 에러코드를 기준으로 알림 시스템을 구축했고 에러 발생시 주문 도메인에서 발생한것인지 혹은 타 도메인에서 주문 도메인을 호출중에 발생한것인지도 파악할 수 있게 구성했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가적으로 파드에 문제가 생기거나 서버자체에 문제가 생겼을때도 즉각적으로 알림이 갈 수 있도록 연동시켰다. 서버로부터 응답시간이 너무 길어져도 문제가 있다고 생각했고 주로 시간에 대한 설정과 과도한 트래픽 발생에 대한 알림 설정을 많이 했던 것 같다. 이렇게 Alert rules을 작성하는게 상당히 재밌었고 이슈발생시 빠르게 대처할 수 있었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2) Kafka 기반 DLQ&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리팀의 서비스가 확장되면서 연동되는 외부 시스템도 늘어나고 처리해야 할 데이터 양도 커졌다. 그에 따라 장애 상황에 빠르게 대응할 수 있는 체계가 필요해졌다. 특히 이렇게 DLQ를 구축시켜 놓으니 트래픽이 갑자기 몰릴 수 있는 큰 이벤트를 진행할때 큰 도움이 됐었다. 장애 발생 시 알림 시스템과 연동한 것도 의미가 있었고 고객대응 측면에서도 큰 도움이 되었다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3) SAGA 기반 분산 트랜잭션 처리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA 환경에서 프로젝트 규모도 점점 커지다보니 이벤트 실패에 따른 데이터 불일치가 종종 발생했다. 특정 도메인의 비즈니스 로직이 변경되면 영향 범위가 넓어져 장애 원인이 명확히 파악되기 전에 문제가 확산된 적도 있었다. 이에 따라 자동 롤백이 가능한 구조가 필요했고, SAGA 패턴이 적합하다고 판단했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-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;2025.02~2025.05&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;이직&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이직에 대한 고민은 2024년부터 시작했던 것 같다. 기존 회사에서의 업무는 익숙하고 편안했다. 시니어 개발자분들이 퇴사하시면서 실력향상을 어떻게 할까 고민하다 개발문화 개선을 위해 주도적으로 팀을 위해 헌신했던 적도 있었고 기술적으로도 자유도가 커서 팀과 함께 성장하기 위해 노력하기도 했었고 여러모로 좋은 경험들을 할 수 있어서 좋았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 시간이 지날수록 새로운 환경과 개발에 대한 욕심이 더 커져만 갔다. 내가 잘 하고 있는건지? 뭔가 뒤쳐지고 있는것은 아닌지?.. 무엇보다 환경에 익숙해지면서 성장에 대한 열망이 사라진게 가장 큰 원인이었다. 환경을 바꿔야 더 성장할 수 있을 것 같아 이직을 준비했다. 러너스하이를 신청했던 이유도 예전처럼 열정을 불태우고 싶어서였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이직을 준비하면서 여러 회사에 지원했지만 가고 싶었던 회사들은 합격 통보를 받지 못해서 한동안 고민이 깊어졌다. 그러던 와중 금융회사의 공고도 살펴보았는데 해당 회사에서 지금까지 없던 새로운 일을 하고 있다고 느껴졌고 재직중인 지인도 있어 한번 넣어보자는 마음으로 지원했는데 의외로 바로 합격했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다른 회사들도 지원 했었지만 연봉이 안 맞거나 면접관 혹은 팀 분위기가 잘 맞지 않을것 같은 곳은 최종합격 후에도 입사하지 않았던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스타트업을 가고 싶은 생각도 있어 스타트업 분들과도 커피챗과 더불어 면접을 몇번 진행했었는데 참 매력적이고 재밌겠다고 느꼈다. 언젠가는 스타트업에서의 생활을 한번 경험해보고 싶은 생각도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음부터 금융권을 가고싶은 생각은 없었다. 금융권은 개발자의 무덤이라는 이야기도 많고 제약이 많은 환경일 것 같아 걱정이 많았었다. 하지만 기존 회사에서 정체되어 있는것보단 새로운 환경에서 도전하는것이 더 재밌을 것 같아 해당 회사로 이직을 결심했다. 또한 집과 거리가 가까워 개인시간이 많이 남으면 퇴근 후 하고 싶은 일을 더 자유롭게 할 수 있겠다는 생각도 했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이직 후 몇달간은 적응기간이었다. 팀 분위기는 정말 좋았고, 사람들도 모두 편안했다. 업무적으로는 이전 커머스 환경과는 개발문화가 많이 달라 혼란스러웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;업무적으로는 이전 커머스 환경과는 많이 달라보였던 이유는 다음과 같았다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;레거시 기술 스택 비중이 높았고&lt;/li&gt;
&lt;li&gt;결정 과정에 시간이 걸렸으며&lt;/li&gt;
&lt;li&gt;데이터와 프로세스 설계가 매우 신중했다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 대신 다음과 같은 점들이 좋았다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대규모 배치 처리에 대한 지식&lt;/li&gt;
&lt;li&gt;복잡한 SQL을 다룬다는 점&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;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇듯 기존에 경험하지 못했던 문제들도 마주해보고 새로운 도메인 지식을 쌓다보니 나름 재미있게 새로운 환경에 적응할 수 있었다. 이렇게 2월부터 5월까지는 이직한 회사에 적응하는 기간을 가졌었다.&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;2025.06&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;개인 프로젝트&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이직한 회사에서는 퇴근이후 개인시간이 많아져서 6월부터는 자연스럽게 내가 만들고 싶은 서비스에 대한 갈증이 올라왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI를 활용한 개인프로젝트를 진행하고 싶었고 개발자 지인 한명과 함께 한달 간 프로젝트를 진행했었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MEMENTO라는 AI를 활용해서 일상&amp;amp;여행일지를 기록하고 공유하기도 하며 스토리를 만드는 프로젝트였는데 초기에는 단순한 요약 또는 추천정도를 AI로 활용하려다가 더 확장됐다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를들어 특정 주제 또는 자유롭게 본인들이 작성하고 싶은 것으로 1명 이상의 사람들과 릴레이 소설을 쓰는 형식이 재미있겠다고 생각했다. SNS를 보면 댓글로 여러 사람이 하나의 이야기를 만드는 것을 간혹 볼 수 있었는데 이를 생각했던 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쨋든 여러 사람이 하나의 스토리를 이어서 쓰고 책처럼 만드는 기능은 재밌겠다고 생각해 추가했다. 처음으로 프롬프트 엔지니어링도 해보면서 즐겁게 프로젝트를 임할 수 있었고 원하던 것들을 전부 구현하지는 못했지만 간만에 vue와 python을 사용해보면서 재미있게 토이프로젝트 형식으로 잘 마무리 할 수 있었다.&lt;s&gt;(백엔드 두명이라 기능동작을 위주로..)&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IUQ01/dJMcafZtL0P/KwHmHyJPQHHOWcT6GKmkK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IUQ01/dJMcafZtL0P/KwHmHyJPQHHOWcT6GKmkK0/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;1245&quot; data-origin-height=&quot;553&quot; data-filename=&quot;image (4).png&quot; style=&quot;width: 65.3853%; margin-right: 10px;&quot; data-widthpercent=&quot;66.94&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IUQ01/dJMcafZtL0P/KwHmHyJPQHHOWcT6GKmkK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIUQ01%2FdJMcafZtL0P%2FKwHmHyJPQHHOWcT6GKmkK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1245&quot; height=&quot;553&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdiJGG/dJMcaaYba2i/FRhpgDQKTa58gjnpey0qJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdiJGG/dJMcaaYba2i/FRhpgDQKTa58gjnpey0qJk/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;752&quot; data-origin-height=&quot;1320&quot; data-filename=&quot;image (5).png&quot; style=&quot;width: 16.5455%; margin-right: 10px;&quot; data-widthpercent=&quot;16.94&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdiJGG/dJMcaaYba2i/FRhpgDQKTa58gjnpey0qJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdiJGG%2FdJMcaaYba2i%2FFRhpgDQKTa58gjnpey0qJk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/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;1320&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZEVNM/dJMcahQwYb2/tkEmhX4CKvah8Axyn5Cz7K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZEVNM/dJMcahQwYb2/tkEmhX4CKvah8Axyn5Cz7K/img.png&quot; data-is-animation=&quot;false&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;1295&quot; data-filename=&quot;image (6).png&quot; style=&quot;width: 15.7436%;&quot; data-widthpercent=&quot;16.12&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZEVNM/dJMcahQwYb2/tkEmhX4CKvah8Axyn5Cz7K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZEVNM%2FdJMcahQwYb2%2FtkEmhX4CKvah8Axyn5Cz7K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;702&quot; height=&quot;1295&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;h2 data-ke-size=&quot;size26&quot;&gt;2025.07&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;7월은 여행도 다니고 놀러다니느라 바빠서 흥청망청 놀았다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2025.08 ~ 2025.12&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;8월부터는 노션정리도 할겸 묵혀놨던 아이디어를 활용해보고 싶었다. 필자는 하고 싶은 프로젝트나 괜찮을것 같은 아이디어가 떠오르면 간단히 메모한뒤 추후에 책상앞에 앉아 어떠한 서비스를 만들면 좋겠다 라는걸 정리하는 편인데 마침 노션에 오래전에 구상했던 프로젝트가 있어 꺼내보았다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래는 수수료제로라는 프로젝트를 하고 싶었는데 대형 플랫폼인 배달어플이나 숙박어플에서 업체로부터 수수료를 과다하게 받고 있다는 생각이 들었고 소상공인들에게는 조금은 불합리한 측면이 있다고 생각해 규모가 작은곳들은 구독형으로 적당한 비용을 내고 규모가 큰곳은 지금처럼 건별 수수료를 내면서 적립형 할인 금액도 쌓을 수 있게 수수료에 대한 부담을 덜어주는 혼합된 방식으로 해보고 싶었는데 혼자서는 너무 시간이 오래 걸릴것 같아 다시 묻어두었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 본래 하려고 했던 AI를 활용한 정치앱을 만들기로 했다. 정치뉴스나 기사, 유튜브를 보면 신뢰할 수 없는 정보들이 너무 많이 돌아다니기 때문에 잘못된 정보들을 보다보면 개인의 판단능력과 가치관이 너무 흔들린다고 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문제를 AI를 활용해 편향되어 있는 정보는 제외시키고 필터를 거쳐 사실적이고 팩트에 기반한 정보만 전달해보면 좋을 것 같다!! 라고 생각했다. 그런데 법률적인 문제나 민감한 요소들이 많아 초기 단계에서 이를 제외시키고 프로젝트를 어떻게 설계해야할지 고심하느라 시간이 좀 소요됐었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로는 AI를 활용해 뉴스 크롤링도 하고 해당 기사의 본문을 살펴보며 다른 언론사에서는 이 주제를 어떻게 다루는지 자료를 모은다음 가장 중립적인 시선으로 작성되었다고 판단한 기사의 본문을 짧게 요약하여 해당 기사의 링크와 사진 제목 본문은 짧게 리스트 형식으로 뿌리는 것이 주된 기능이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;수집된 정보로 AI에게 의견을 받거나 가공된 정보 없이 양질의 정보만 전달하고 사용자들에게 판단을 맡기고 싶었다.&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;li&gt;가장 중립적인 시선을 판단하는 부분이 어려웠는데 이것저것 실험을 많이 해보다가 생각한것은 각 메이저 언론사별로 비중을 분할했었다. 그러다 외신 기사의 객관성이 높다고 생각해 비중을 높여서 설정했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앱 프로젝트를 도전하는건 처음이라 우여곡절이 많았고 앱을 출시하긴 했지만 아직 가공해야할 부분들이 많아 좀 더 고도화를 시켜야 만족스러운 결과물이 나올 것 같다. 조금씩 고도화 시키면서 조용히 운영해볼 생각이다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 앱이다 보니 프롬프트를 고도화 하는 작업이나 &amp;ldquo;사용자가 실제로 어떻게 쓸까? &amp;ldquo;어떻게 해야 빠른 속도로 크롤링해서 사용자에게 보여줄까?&amp;rdquo; 등등 이걸 고민하면서 개발하는 시간이 정말 즐거웠던것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로토타입 버전의 사진이 있어 기념으로 올렸다 ㅎㅎ.. 출시버전에서는 UI를 흰 배경으로 하고 전체적으로 깔끔하게 보이도록 바꿔버렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image (7).png&quot; data-origin-width=&quot;972&quot; data-origin-height=&quot;1423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uqR8N/dJMcaiomsFp/fvzqRsVMTUkBsOr4fcj910/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uqR8N/dJMcaiomsFp/fvzqRsVMTUkBsOr4fcj910/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uqR8N/dJMcaiomsFp/fvzqRsVMTUkBsOr4fcj910/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuqR8N%2FdJMcaiomsFp%2FfvzqRsVMTUkBsOr4fcj910%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;350&quot; height=&quot;512&quot; data-filename=&quot;image (7).png&quot; data-origin-width=&quot;972&quot; data-origin-height=&quot;1423&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;느슨한 모임&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 회고를 쓰게된것도 글또에서 파생된 이 모임때문에 작성했는데 모이신분들도 대단하시고 다양한 생각과 경험을 가지고 있으셔서 듣는것도 너무 즐거웠다. 이렇게 회고를 해보니 좋았던 기억이 많아서 이제부터는 매년 작성해보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글또분들에게는 항상 좋은 영향을 받는일이 많아서 매번 참 감사한것 같다. 느슨한 모임의 회고는 피그잼으로 진행했고 4개의 섹션으로 나누어 각 섹션별로 마음에 드는 질문을 여러개 골라서 답변한뒤 발표 후 궁금한점에 대해 질문하는 방식이었다. 전부 한해를 돌아볼 수 있는 질문들이어서 좋았다. 자세한 내용은 필자가 만든 모임이 아니기도 해서 올리기 애매한것 같아 피그잼 템플릿 제목만 올리겠다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image (8).png&quot; data-origin-width=&quot;695&quot; data-origin-height=&quot;64&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d7Gsqt/dJMcafLWUpH/bKyOKakioh1KTAgukN0nP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d7Gsqt/dJMcafLWUpH/bKyOKakioh1KTAgukN0nP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d7Gsqt/dJMcafLWUpH/bKyOKakioh1KTAgukN0nP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd7Gsqt%2FdJMcafLWUpH%2FbKyOKakioh1KTAgukN0nP1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;695&quot; height=&quot;64&quot; data-filename=&quot;image (8).png&quot; data-origin-width=&quot;695&quot; data-origin-height=&quot;64&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;마무리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2025년을 완전히 만족스럽게 보내지는 못했지만 목표로 했던 것들에 조금씩은 다가가고 있는 것 같아 완전 실패는 아닌것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 실행력이 좀 부족했던 것도 있고 왠지 모르게 올해는 의욕이 많이 생기지 않아서(너무 놀아서 그런건지..) 작년보다는 최선을 다하지는 못했기에 개인적으로 아쉬운 측면도 있엇다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2025년에는 여행도 자주 갔고 취미생활도 많이 늘어서 좋은 해였다. 중국,태국,베트남,미국 여행을 갔다왔었고 대회를 나가서 한강에서 수영으로 반대편까지 헤엄쳐보기도 하고 북한산에서 처음으로 암벽등반도 해보며 하네스도 착용해봤었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히나 회사 근처에 남산이 있어서 자주 트레일런을 했었던것도 좋았었다. 회사까지 출퇴근을 러닝으로 해보기도 했었는데 이건 너무 힘들어서 다시 생각나지 않는 이상은 안할것같다ㅎ...&lt;br /&gt;&lt;br /&gt;이렇게 작성해보니 내년에는 올해보다는 노는걸 줄이고 커리어적으로 더 열심히 살아야겠다는 생각을 했다. 처음으로 회고를 진행해봤는데 정말 좋은 점이 많은것 같다. 내년부터는 더 열심히 정진해야겠다..&lt;/p&gt;</description>
      <category>회고</category>
      <category>2025</category>
      <category>개발자</category>
      <category>회고</category>
      <author>sjoongh</author>
      <guid isPermaLink="true">https://sjoongh.tistory.com/67</guid>
      <comments>https://sjoongh.tistory.com/entry/2025-%EA%B0%9C%EB%B0%9C%EC%9E%90-%ED%9A%8C%EA%B3%A0#entry67comment</comments>
      <pubDate>Sun, 21 Dec 2025 13:39:01 +0900</pubDate>
    </item>
    <item>
      <title>글또 10기 회고</title>
      <link>https://sjoongh.tistory.com/entry/%EA%B8%80%EB%98%90-10%EA%B8%B0-%ED%9A%8C%EA%B3%A0%EB%A7%88%EC%A7%80%EB%A7%89-%EA%B8%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 글또 9, 10기에 참여했고 정말 귀중한 시간들과 글또 분들에게 선한 영향력을 받으며 많은 자극을 받아 더욱 성장할 수 있었습니다. 아쉽게도 공식적인 글또의 여정은 10기에서 마무리되지만, 마지막이라고 실감나지는 않고 글또 분들과 지속적으로 소통을 이어나가려고 노력해볼 예정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글또를 처음 시작한 9기부터 새롭게 성장하는 계기가 된 것 같습니다. 정말 많은 일들에 새롭게 도전하고 실패도 많이 했습니다. 아마 지금의 개발자로서 저를 만든것에 일조한 것이 글또를 시작한 일이라고 말할 수 있을 것 같습니다. 정말 아쉽게 느껴지기도 하고 시간이 이렇게 빠르게 흘러갔나?.. 싶기도 합니다. 글또분들은 다들 따뜻하고 좋으신 분들이니 어디서든 마주한다면 반갑게 인사를 나누었으면 좋겠습니다ㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-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;1. 버츄얼 소개팅 아바타 앱 제작&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘 같이 새로운 사람을 쉽게 만나기 힘든 분위기에서는 결국엔 사람 간의 관계로 수익을 벌 수 있는 요소가 많을 것이라고 생각했습니다. 외국의 경우는 쉽게 처음 보는 사람과 친해지기 쉽고 낯선 사람과 편안하게 말을 주고받는 분위기인 반면 아시아권은 유교사상과 예절이 몸에 베어있기 때문인지 존댓말이라는 개념 때문인지 낯선 이와 대화를 시도하기가 쉽지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쨌든 세상이 달라져도 사람 간의 관계에 대해 고민하고 이에 대해 부수적으로 수익화를 할 수 있는 이 요소는 달라지지 않을 것이라고 생각했고, 적당한 게 무엇이 있을까 생각하다 소개팅 어플이 재미있어 보였습니다. 기존에 소개팅 어플은 자신의 사진을 올려 외적인 것을 먼저 평가하는 것이 주이고, 이러한 요소들 때문에 가벼운 만남이라고 보여지는 부분이 없지 않아 있다고 생각했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때문에 필자는 유저가 회원가입을 할 때 본인을 대표할 수 있는 가상 아바타를 만들면 어떨까 하는 생각을 했습니다. 물론 기존 소개팅처럼 취미나 취향 같은 것은 공개하지만, 본인의 얼굴이 아닌 아바타가 보이는 점이 외적인 것을 보지 않고 상대방의 내면을 먼저 바라보고 호감이 생기기를 원했던 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 대다수의 소개팅 어플들은 상대방과 대화를 하려면 결제를 진행해야 하는데, 제가 만들고 싶은 건 자유롭게 대화를 진행하고 상대방의 '진짜' 얼굴이 보고 싶을 때는 결제를 진행해 상대 유저가 업로드한 본인의 셀카 사진을 볼 수 있도록 구성하면 거기서 수익을 얻을 수 있을 것이라고 생각했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-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;2. 유튜브 쇼츠 시작&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;뼈아픈 앱 프로젝트 실패 이후 부업으로 할 만한 다른 일이 무엇이 있을까 생각하다가 AI로 동영상을 만들어서 양산형 쇼츠 채널을 만들면 수익적으로 도움이 될 수 있다고 판단했고, IT-기술분야, 요리 두 가지 채널을 만들어서 운영했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-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;3. 여행 &amp;amp; 맛집 소개 프로젝트&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여행과 맛집 소개 프로젝트는 절대적으로 신뢰감을 주는 앱이나 사이트가 없다고 생각해 시작하게 되었고 이 프로젝트는 성공적으로 출시해 초기 서비스를 진행했지만 함께 진행했던 친구와 서비스를 진행시키는 관점이 점차 너무나도 달라지기도 했고 제가 생각했던 방향과는 점차 달라지는 것이 느껴졌기에 제가 추구하지 않는 서비스를 제공하는 것 같아 잠시 멈추었습니다.&lt;br /&gt;&lt;br /&gt;이후에 지인이 아닌 사람들로 구성된 새로운 팀원들을 구해 진행하려고 했지만!! 마침 하반기 이직 시즌이었기에 이력서 작성과 면접준비 그리고 회사 업무도 너무나도 바빠져 2025년에 시간이 난다면 제가 추구했던 방향으로 다시 진행해보려고 하고 있습니다 ㅎ..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;글또와 함께했기 때문에&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글또에서는 단 한 번도 쓴 적 없었지만 작년에는 위의 글에 작성한 내용들을 주로 진행했었고, 글또에 제출하는 글들은 개인적으로 궁금하거나 업무 중에 처리했던 일 혹은 모르는 사항이 생기면 전부 글감으로 삼아 제출할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다 연말에는 제가 하고 싶은 공부나 개발자로서 성장에 조금은 소홀하게 대한 것 같아 듣고 싶었던 AI 교육도 맛보기로 수강해보고 토스 러너스하이도 수행하며 더 적극적으로 성장에 임할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;글또에서는 많은 대단하신 분들한테 자극을 받은 덕분에 작년에는 새로운 일들에 많이 도전해봤던 것 같습니다. 올해에도 또 다른 도전을 이어나가고 있지만, 글또의 다른 분들에 비하면 의욕이나 열정이 부족해 끝까지 밀고 가는 힘이 부족한 것 같기도 합니다. 그래서 올해에는 더욱 적극적으로 임해볼 생각입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 많은 성장 동력과 에너지를 준 글또에게 정말 감사드리고 비록 공식적인 활동은 곧 끝나지만 글또를 통해 얻은 글쓰기 습관과 꾸준함의 가치는 앞으로의 발전에도 큰 도움이 될 것이라고 느끼고 있습니다. 또한 글또에서 만난 다양한 분야의 개발자들과의 네트워킹은 정말 많은 도움이 되었고 저도 다른 사람들에게 선한 영향력을 줄 수 있게 노력해야 겠다고 많이 생각했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 동안 커피챗을 많이 못했던 것 도 너무 아쉽게 느껴집니다ㅠ.. 그래도 이게 끝이 아니니 기회가 있으면 다른 분들도 더 만나봐야 겠다는 생각도 들었습니다!! &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;앞으로도&lt;span&gt; &lt;/span&gt;&lt;/span&gt;글또의 정신을 이어받아 앞으로도 꾸준히 기록하고 공유하며 함께 성장하는 개발자가 되겠습니다! 글또 분들이 갑자기 어디로 사라지는게 아니니 이번 10기 활동이 글또의 마지막이 아닌 글또분들과 지속적인 소통과 만남 그리고 새로운 마음가짐으로 임할 수 있는 또 다른 기회라고 생각할 것 같습니다. 앞으로도 글또 분들과도 오랫동안 함께 성장해나가면 좋겠네요!!!&lt;/p&gt;</description>
      <category>활동</category>
      <category>10기</category>
      <category>글또</category>
      <category>글또10기</category>
      <category>마지막</category>
      <category>회고</category>
      <author>sjoongh</author>
      <guid isPermaLink="true">https://sjoongh.tistory.com/66</guid>
      <comments>https://sjoongh.tistory.com/entry/%EA%B8%80%EB%98%90-10%EA%B8%B0-%ED%9A%8C%EA%B3%A0%EB%A7%88%EC%A7%80%EB%A7%89-%EA%B8%80#entry66comment</comments>
      <pubDate>Sun, 30 Mar 2025 23:46:41 +0900</pubDate>
    </item>
    <item>
      <title>개발자의 시선에서 노션 살펴보기</title>
      <link>https://sjoongh.tistory.com/entry/%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-%EC%8B%9C%EC%84%A0%EC%97%90%EC%84%9C-%EB%85%B8%EC%85%98-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;노션은 단순한 메모 앱을 넘어 문서 편집, 데이터베이스 관리, 프로젝트 협업까지 가능한 올인원 협업툴이라고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 사용자가 노션을 선호하는 이유는 직관적인 UI와 다양한 기능이라고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자도 노션을 애용하고 있었기에 문득 &lt;b&gt;어떤 기능들이 어떻게 구현되었을까?&lt;/b&gt; 하는 궁금증이 생겼습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 글에서는 백엔드 개발자의 시각에서 노션의 주요 기능들이 어떻게 동작하는지, 그리고 노션이 다른 메모 서비스와 비교하여 어떤 기술적 차별점을 가지는지 추측 겸 분석해보겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2. 노션의 주요 기능 분석&lt;br /&gt;&lt;br /&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2.1 블록 기반 데이터 모델&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노션의 가장 큰 특징 중 하나는 &lt;b&gt;블록 기반 데이터 모델이라는 것입니다.&lt;/b&gt; 일반적인 문서 편집기는 연속된 텍스트를 하나의 문서로 저장하지만, 노션은 모든 콘텐츠(텍스트, 이미지, 테이블, 데이터베이스 등)를 블록 단위로 저장합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;블록은 독립적인 엔티티&lt;/b&gt;: 각 블록은 고유한 ID를 가지며 데이터베이스 내에서 개별적으로 저장 및 수정되며 관리하고 있는 것 같습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;트리 구조 지원&lt;/b&gt;: 블록은 부모-자식 관계를 형성하며 계층적인 문서를 쉽게 구성할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;버전 관리 용이&lt;/b&gt;: 블록 단위로 변경 사항을 추적할 수 있어 협업 및 롤백이 쉽습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;2.2 실시간 협업 및 WebSocket 기반 아키텍처&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노션은 여러 사용자가 동시에 같은 문서를 편집할 수 있도록 실시간 협업 기능을 제공합니다. 이를 위해 WebSocket 기반의 &lt;b&gt;실시간 동기화&lt;/b&gt;를 사용합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;WebSocket 연결 유지&lt;/b&gt;: 클라이언트는 서버와 지속적으로 연결된 상태에서 변경 사항을 주고받습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Operational Transformation(OT) 또는 Conflict-Free Replicated Data Types (CRDT)&lt;/b&gt;: 충돌 방지 및 데이터 일관성을 유지하기 위한 기술을 적용할 것 같습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이벤트 기반 업데이트&lt;/b&gt;: 서버는 변경 사항이 발생하면 해당 블록을 수정한 사용자에게만 업데이트를 전송하여 불필요한 데이터 전송을 줄입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;2.3 데이터베이스 기능과 쿼리 최적화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노션의 데이터베이스 기능은 일반적인 SQL 기반 데이터베이스와 다르게 동작합니다. 노션의 데이터베이스는 다양한 필터링, 정렬, 관계(Relation), 롤업(Rollup) 기능을 제공하며 이를 위해 &lt;b&gt;GraphQL 및 NoSQL 스타일의 데이터 저장 방식&lt;/b&gt;을 활용할 가능성이 크다고 생각했습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;스키마리스(Schemaless) 저장 방식&lt;/b&gt;: 각 테이블이 동적인 컬럼을 가질 수 있어 유연한 데이터 구조를 지원할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;캐싱 및 인덱싱 최적화&lt;/b&gt;: 자주 사용하는 데이터는 인덱싱 및 Redis 같은 인메모리 캐싱을 활용하여 성능을 높입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JSON 기반 쿼리 시스템&lt;/b&gt;: 사용자 인터페이스에서 직접 필터와 정렬을 설정하면 이를 백엔드에서 JSON 기반의 쿼리로 변환하여 실행시키는 방식이 유력합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;2.4 권한 관리 및 액세스 제어&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노션은 문서 단위로 다양한 권한을 설정할 수 있습니다. 이를 위해 &lt;b&gt;RBAC(Role-Based Access Control) 및 ACL(Access Control List) 모델&lt;/b&gt;을 혼합하여 사용하고 있을 가능성이 높습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;역할 기반 접근 제어(RBAC)&lt;/b&gt;: 각 사용자는 특정 문서에 대해 '읽기', '편집', '관리' 권한을 가질 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;공유 링크 기반 접근 제어&lt;/b&gt;: 비회원도 특정 링크를 통해 문서를 조회할 수 있도록 토큰 기반 인증을 활용합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;워크스페이스 단위 권한 설정&lt;/b&gt;: 팀 단위 권한 관리가 가능하도록 구조화되어 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;br /&gt;2.5 개인적으로 재밌었던 기능&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;멘션 기능&lt;/b&gt;: 실시간으로 사용자 및 페이지 ID를 검색하여 링크를 생성하는 방식으로 동작합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;임베드 기능&lt;/b&gt;: Open Graph API를 사용하여 외부 콘텐츠의 메타데이터를 가져와 미리보기를 생성합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;북마크 기능&lt;/b&gt;: URL을 입력하면 Open Graph 태그를 이용해 제목, 설명, 이미지 등을 자동으로 가져와 노출합니다.
&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;pre id=&quot;code_1741782048686&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import requests
from bs4 import BeautifulSoup

def fetch_url_metadata(url):
    try:
        response = requests.get(url)
        response.raise_for_status()  # HTTP 에러 발생 시 예외 처리
    except requests.exceptions.RequestException as e:
        print(f&quot;Failed to fetch URL: {e}&quot;)
        return None

    # HTML 파싱
    soup = BeautifulSoup(response.text, 'html.parser')

    # 메타 데이터 추출
    title = soup.title.string if soup.title else &quot;No title available&quot;

    description = None
    og_description = soup.find(&quot;meta&quot;, property=&quot;og:description&quot;)
    meta_description = soup.find(&quot;meta&quot;, attrs={&quot;name&quot;: &quot;description&quot;})
    if og_description:
        description = og_description.get(&quot;content&quot;)
    elif meta_description:
        description = meta_description.get(&quot;content&quot;)
    else:
        description = &quot;No description available&quot;

    # OG 이미지 또는 favicon 추출
    og_image = soup.find(&quot;meta&quot;, property=&quot;og:image&quot;)
    favicon = soup.find(&quot;link&quot;, rel=&quot;icon&quot;)

    image_url = og_image.get(&quot;content&quot;) if og_image else &quot;No image available&quot;
    favicon_url = favicon.get(&quot;href&quot;) if favicon else &quot;No favicon available&quot;

    # 절대 URL 처리
    if image_url and not image_url.startswith(&quot;http&quot;):
        image_url = requests.compat.urljoin(url, image_url)
    if favicon_url and not favicon_url.startswith(&quot;http&quot;):
        favicon_url = requests.compat.urljoin(url, favicon_url)

    return {
        &quot;url&quot;: url,
        &quot;title&quot;: title,
        &quot;description&quot;: description,
        &quot;images&quot;: [{&quot;url&quot;: image_url}],
        &quot;favicon_url&quot;: favicon_url
    }

# 테스트 출력
metadata = fetch_url_metadata(&quot;https://www.example.com&quot;)
print(metadata)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 노션이 다른 메모 서비스와 차별화되는 이유&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노션은 단순한 메모 앱이 아니라 협업 및 데이터 관리 기능이 결합된 생산성 플랫폼입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 가능하게 하는 주요 기술적 차별점은 있겠지만 필자가 느끼기에 노션을 사용하는 가장 큰 이유는 다음과 같습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;블록 기반 데이터 모델로 인한 자유로운 커스터마이징(제품의 유연성)&lt;/li&gt;
&lt;li&gt;단순하고 직관적인 인터페이스&lt;/li&gt;
&lt;li&gt;실시간 협업과 공유&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로는 이 중에서도 편리한 구조의 인터페이스가 가장 큰 영역을 차지하는 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 마무리&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노션은 강력한 블록 기반 데이터 모델, WebSocket을 활용한 실시간 협업, 유연한 데이터베이스 구조를 통해 기존 메모 앱과 차별화된 생산성 도구로 자리 잡았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;요즘에는 노션의 템플릿을 모방한 웹이나 모바일 앱도 심심치 않게 찾아볼 수 있습니다. 그만큼 노션은 많은 협업툴에 영향을 끼친 것 같기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자 관점에서 보는 노션은 &lt;b&gt;효율적인 데이터 모델링과 성능 최적화를 위한 다양한 기술 스택이 활용&lt;/b&gt;되고 있음을 알 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;노션의 기술을 분석하면서 얻은 인사이트는&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;확장성이 뛰어난 시스템을 설계하려면 어떻게 해야하는가?&lt;/li&gt;
&lt;li&gt;편리한 서비스를 제공하기 위해서는 어떻게 해야할까?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞선 질문에 대해 고민해볼 수 있었고 개발을 진행함에 있어 중요한 요소가 무엇인지 생각해볼 수 있었습니다.&lt;/p&gt;</description>
      <category>기타</category>
      <category>notion</category>
      <category>개발자</category>
      <category>노션</category>
      <author>sjoongh</author>
      <guid isPermaLink="true">https://sjoongh.tistory.com/65</guid>
      <comments>https://sjoongh.tistory.com/entry/%EA%B0%9C%EB%B0%9C%EC%9E%90%EC%9D%98-%EC%8B%9C%EC%84%A0%EC%97%90%EC%84%9C-%EB%85%B8%EC%85%98-%EC%82%B4%ED%8E%B4%EB%B3%B4%EA%B8%B0#entry65comment</comments>
      <pubDate>Sun, 16 Mar 2025 15:10:21 +0900</pubDate>
    </item>
    <item>
      <title>데이터베이스 성능 최적화 고찰</title>
      <link>https://sjoongh.tistory.com/entry/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC</link>
      <description>&lt;p data-end=&quot;529&quot; data-start=&quot;420&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대규모 서비스를 운영하다 보면 &lt;b&gt;데이터 저장 방식, 쿼리 최적화, 트랜잭션 관리, 대용량 데이터 처리&lt;/b&gt;가 서비스 성능에 직접적인 영향을 미치기도 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;529&quot; data-start=&quot;420&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;529&quot; data-start=&quot;420&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;잘못된 데이터 모델링, 비효율적인 쿼리, 인덱스 활용 부족&lt;/b&gt; 등이 문제를 일으킬 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;610&quot; data-start=&quot;531&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;610&quot; data-start=&quot;531&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 글에서는 PostgreSQL과 MySQL을 기반으로 쿼리 최적화, 대용량 데이터 처리, 트랜잭션 설계를 위한 전략을 정리해 봤습니다.&lt;/span&gt;&lt;/p&gt;
&lt;h2 data-end=&quot;647&quot; data-start=&quot;617&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-end=&quot;647&quot; data-start=&quot;617&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1. 성능 최적화 전 선행 작업&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p data-end=&quot;458&quot; data-start=&quot;375&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;458&quot; data-start=&quot;375&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;백엔드 개발자로서 성능 개선을 고민할 때, 단순히 &quot;이 쿼리를 최적화하자&quot; 수준이 아니라 &lt;b&gt;서비스의 데이터 처리 패턴을 먼저 이해해야 한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;458&quot; data-start=&quot;375&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;490&quot; data-start=&quot;460&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1.1 데이터 액세스 패턴 분석&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-end=&quot;536&quot; data-start=&quot;491&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;536&quot; data-start=&quot;493&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;우리 서비스는 읽기(조회) 비중이 높은가? 쓰기(저장) 비중이 높은가?&quot;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;642&quot; data-start=&quot;537&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;584&quot; data-start=&quot;537&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;읽기 중심 서비스&lt;/b&gt; (예: 뉴스 피드, 검색 엔진) &amp;rarr; 캐싱 전략이 중요&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;642&quot; data-start=&quot;585&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;쓰기 중심 서비스&lt;/b&gt; (예: IoT 센서 데이터 저장) &amp;rarr; 배치 처리, 비동기 큐 활용 고려&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-end=&quot;687&quot; data-start=&quot;644&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;687&quot; data-start=&quot;646&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;어떤 쿼리가 가장 자주 실행되며, 어떤 부분에서 병목이 발생하는가?&quot;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;841&quot; data-start=&quot;688&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;736&quot; data-start=&quot;688&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Slow Query Log 분석&lt;/b&gt; (long_query_time 설정)&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;763&quot; data-start=&quot;737&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;EXPLAIN ANALYZE&lt;/b&gt; 활용&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;841&quot; data-start=&quot;764&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;APM (Application Performance Monitoring)&lt;/b&gt; 툴 연동 (예: New Relic, Datadog)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;881&quot; data-start=&quot;843&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 data-end=&quot;881&quot; data-start=&quot;843&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1.2 현재 데이터 모델과 트랜잭션 설계 점검&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-end=&quot;920&quot; data-start=&quot;882&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터베이스의 정규화 vs 반정규화 여부를 검토해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1021&quot; data-start=&quot;921&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;968&quot; data-start=&quot;921&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;정규화&lt;/b&gt;: 데이터 중복을 방지하지만, 조인이 많아질 경우 성능 저하 가능&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1021&quot; data-start=&quot;969&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;반정규화&lt;/b&gt;: 성능 최적화를 위해 중복 저장을 허용하지만, 데이터 정합성 관리 필요&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1055&quot; data-start=&quot;1023&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트랜잭션 격리 수준도 성능에 큰 영향을 미친다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1209&quot; data-start=&quot;1056&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1106&quot; data-start=&quot;1056&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;READ COMMITTED&lt;/b&gt; (기본 설정) &amp;rarr; 일반적인 서비스에서 무난한 선택&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1161&quot; data-start=&quot;1107&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;REPEATABLE READ&lt;/b&gt; (MySQL 기본) &amp;rarr; 트랜잭션이 길어지면 데드락 위험&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1209&quot; data-start=&quot;1162&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;SERIALIZABLE&lt;/b&gt; &amp;rarr; 데이터 정합성은 보장되지만, 성능 저하 가능&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1741782867377&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SET TRANSACTION ISOLATION LEVEL READ COMMITTED;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-end=&quot;1120&quot; data-start=&quot;1096&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-end=&quot;1120&quot; data-start=&quot;1096&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2. 성능 최적화 방법&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;h3 data-end=&quot;1356&quot; data-start=&quot;1309&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2.1 인덱스 최적화: 왜 자동 인덱스에 의존하면 안 되는가?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;blockquote data-end=&quot;1413&quot; data-start=&quot;1357&quot; data-ke-style=&quot;style2&quot;&gt;
&lt;p data-end=&quot;1413&quot; data-start=&quot;1359&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&quot;데이터베이스가 자동으로 인덱스를 만들어주니까, 따로 관리 안 해도 되는 거 아닌가?&quot;&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end=&quot;1464&quot; data-start=&quot;1415&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1464&quot; data-start=&quot;1415&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아니다. 실무에서는 인덱스가 &lt;b&gt;과하게 걸려서 성능이 오히려 저하되는 경우&lt;/b&gt;도 많다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1575&quot; data-start=&quot;1465&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1506&quot; data-start=&quot;1465&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;B-Tree 인덱스&lt;/b&gt; &amp;rarr; 일반적인 WHERE 검색 조건에 적합&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1544&quot; data-start=&quot;1507&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;GIN 인덱스&lt;/b&gt; &amp;rarr; JSONB, Full-Text 검색&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1575&quot; data-start=&quot;1545&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Hash 인덱스&lt;/b&gt; &amp;rarr; 정확한 값 일치 검색&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1741782953835&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE INDEX idx_user_email ON users(email);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;자주 발생하는 인덱스 실수&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;모든 컬럼에 인덱스를 걸어야 한다?&quot; &amp;rarr; 인덱스가 많으면 쓰기 성능이 오히려 저하됨&lt;/li&gt;
&lt;li&gt;&quot;LIKE 검색에는 인덱스가 적용된다?&quot; &amp;rarr; %keyword% 패턴에서는 인덱스가 무용지물&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;해결 방법중 하나는 &quot;Partial Index + Covering Index&quot; 활용하는 것&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1741783035132&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE INDEX idx_active_users ON users(is_active) WHERE is_active = true;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;1980&quot; data-start=&quot;1928&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2.2 쿼리 성능 튜닝: EXPLAIN ANALYZE로 병목 구간 찾기&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-end=&quot;2044&quot; data-start=&quot;1981&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;PostgreSQL과 MySQL 모두 EXPLAIN ANALYZE를 활용하면 실행 계획을 확인할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;pre id=&quot;code_1741783127005&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 123;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-end=&quot;2224&quot; data-start=&quot;2116&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. Seq Scan(전체 스캔) vs Index Scan(인덱스 사용) 차이를 확인할 수 있다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. Index Scan이 나오지 않는다면?&lt;b&gt; &amp;rarr; 인덱스 최적화 필요&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-end=&quot;2261&quot; data-start=&quot;2231&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2.3 대용량 데이터 처리 전략&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-end=&quot;2313&quot; data-start=&quot;2262&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스가 성장하면서 데이터가 몇십만, 몇백만 건을 넘어가면 기존 설계가 한계에 부딪힌다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2354&quot; data-start=&quot;2315&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2354&quot; data-start=&quot;2315&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2354&quot; data-start=&quot;2315&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;테이블 파티셔닝 (Partitioning) 활용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2354&quot; data-start=&quot;2315&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2354&quot; data-start=&quot;2315&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-size: 16px; letter-spacing: 0px;&quot;&gt;&quot;대용량 데이터를 한 테이블에 몰아넣으면 검색 속도가 느려진다!&quot;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2489&quot; data-start=&quot;2396&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2447&quot; data-start=&quot;2396&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;PostgreSQL&lt;/b&gt;: RANGE, LIST, HASH 파티셔닝 지원&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2489&quot; data-start=&quot;2448&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MySQL&lt;/b&gt;: PARTITION BY RANGE 활용 가능&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1741783189628&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE TABLE orders_2024 PARTITION OF orders FOR VALUES FROM ('2024-01-01') TO ('2024-12-31');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2619&quot; data-start=&quot;2598&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2619&quot; data-start=&quot;2598&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;캐싱 전략 적용&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2619&quot; data-start=&quot;2598&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2653&quot; data-start=&quot;2620&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모든 요청을 데이터베이스에서 직접 처리하면 부담이 크다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2748&quot; data-start=&quot;2654&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2696&quot; data-start=&quot;2654&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Redis, Memcached&lt;/b&gt; &amp;rarr; 자주 조회하는 데이터를 캐싱&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2748&quot; data-start=&quot;2697&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Materialized View&lt;/b&gt; &amp;rarr; 정적인 데이터는 미리 생성하여 빠르게 조회&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1741783205244&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;CREATE MATERIALIZED VIEW user_summary AS SELECT user_id, COUNT(*) FROM orders GROUP BY user_id;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p data-end=&quot;2888&quot; data-start=&quot;2858&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2888&quot; data-start=&quot;2858&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2888&quot; data-start=&quot;2858&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;비동기 처리 &amp;amp; 이벤트 큐 활용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2985&quot; data-start=&quot;2889&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2938&quot; data-start=&quot;2889&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Kafka, RabbitMQ&lt;/b&gt; &amp;rarr; 트래픽이 몰릴 때 백그라운드 작업으로 처리&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;2985&quot; data-start=&quot;2939&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Batch Processing&lt;/b&gt; &amp;rarr; 하루 한 번씩 통계를 계산하여 저장&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;h3 data-end=&quot;1837&quot; data-start=&quot;1803&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2.4 데이터 모델링 &amp;amp; 트랜잭션 설계&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-end=&quot;1856&quot; data-start=&quot;1838&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;정규화 &amp;amp; 반정규화&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;1932&quot; data-start=&quot;1857&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;1883&quot; data-start=&quot;1857&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정규화를 통해 데이터 중복을 방지&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;1932&quot; data-start=&quot;1884&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하지만 성능이 중요하다면 &lt;b&gt;반정규화&lt;/b&gt;를 활용해 특정 데이터를 중복 저장 가능&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;1955&quot; data-start=&quot;1934&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;1955&quot; data-start=&quot;1934&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;트랜잭션 격리 수준 설정&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2021&quot; data-start=&quot;1956&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2021&quot; data-start=&quot;1956&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 정합성을 보장하기 위해 &lt;b&gt;READ COMMITTED, SERIALIZABLE&lt;/b&gt; 등의 격리 수준 설정&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1741782590325&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SET TRANSACTION ISOLATION LEVEL READ COMMITTED;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 data-end=&quot;2245&quot; data-start=&quot;2219&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h3 data-end=&quot;2245&quot; data-start=&quot;2219&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;3. 모니터링 &amp;amp; 유지보수 전략&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-end=&quot;2245&quot; data-start=&quot;2219&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무에서 쿼리 성능을 주기적으로 모니터링하지 않으면&amp;nbsp;언제 성능이 저하되는지 알 수 없다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-end=&quot;2245&quot; data-start=&quot;2219&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;PostgreSQL 모니터링 도구 &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3209&quot; data-start=&quot;3142&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3180&quot; data-start=&quot;3142&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;pg_stat_statements &amp;rarr; 가장 느린 쿼리 찾기&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;3209&quot; data-start=&quot;3181&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;pgBadger &amp;rarr; 실행 계획 자동 분석&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MySQL 모니터링 도구&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;3300&quot; data-start=&quot;3233&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;3268&quot; data-start=&quot;3233&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Performance Schema &amp;rarr; 쿼리 성능 분석&lt;/span&gt;&lt;/li&gt;
&lt;li data-end=&quot;3300&quot; data-start=&quot;3269&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Slow Query Log &amp;rarr; 느린 쿼리 감지&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;2426&quot; data-start=&quot;2407&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;2426&quot; data-start=&quot;2407&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;자동화 스크립트 적용&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;2456&quot; data-start=&quot;2427&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2456&quot; data-start=&quot;2427&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;주기적으로 실행 계획을 확인하는 스크립트 작성&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1741782608850&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT * FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h3 data-end=&quot;2557&quot; data-start=&quot;2543&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-end=&quot;2557&quot; data-start=&quot;2543&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;4. 결론&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-end=&quot;2656&quot; data-start=&quot;2558&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;정리하자면 데이터베이스 성능 개선을 위해서는 다음 순서에 따라 진행하는 것이 좋다!&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;2656&quot; data-start=&quot;2558&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;요구사항 분석 &amp;rarr; 현재 시스템 이해 &amp;rarr; 최적화 적용 &amp;rarr; 성능 검증 &amp;rarr; 지속적인 모니터링 필수&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-end=&quot;2656&quot; data-start=&quot;2558&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-end=&quot;2656&quot; data-start=&quot;2558&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;요약&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-end=&quot;3623&quot; data-start=&quot;3428&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. &lt;b&gt;데이터 액세스 패턴을 분석&lt;/b&gt;하여 최적화 방향을 설정&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. &lt;b&gt;적절한 인덱스 설계&lt;/b&gt;와 쿼리 튜닝을 적용&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;3. &lt;b&gt;대용량 데이터 처리 기법&lt;/b&gt;(파티셔닝, 캐싱, 비동기 처리) 활용&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. &lt;b&gt;모니터링 시스템을 구축&lt;/b&gt;하여 지속적인 성능 개선&lt;/span&gt;&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;3720&quot; data-start=&quot;3625&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;3720&quot; data-start=&quot;3625&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;백엔드 개발자로서 데이터베이스 성능은 단순한 튜닝이 아니라, 시스템 설계 단계부터 고려해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;2724&quot; data-start=&quot;2658&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-is-only-node=&quot;&quot; data-is-last-node=&quot;&quot; data-end=&quot;2724&quot; data-start=&quot;2658&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;서비스를 운영하면서 성능 개선이 필요하다면 위의 전략을 하나씩 적용해보자&lt;/span&gt;&lt;/p&gt;</description>
      <category>DB</category>
      <category>PostgreSQL</category>
      <category>암호화</category>
      <author>sjoongh</author>
      <guid isPermaLink="true">https://sjoongh.tistory.com/64</guid>
      <comments>https://sjoongh.tistory.com/entry/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC#entry64comment</comments>
      <pubDate>Sun, 2 Mar 2025 23:29:53 +0900</pubDate>
    </item>
    <item>
      <title>토스 러너스하이 서버 1기 백엔드 과정 후기</title>
      <link>https://sjoongh.tistory.com/entry/%ED%86%A0%EC%8A%A4-%EB%9F%AC%EB%84%88%EC%8A%A4%ED%95%98%EC%9D%B4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-%ED%9B%84%EA%B8%B0</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;토스 러너스 하이란?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;토스 러너스 하이는 개발 실무 경력이 있는 서버 개발자를 위한 프로그램입니다. 2024년 12월 16일부터 2025년 1월 16일까지 약 한 달간 진행된 교육에 참여할 수 있었습니다. 아 참고로 이번이 처음으로 시행하는 서버 1기였습니다 ㅎㅎ 2025년부터는 추가 기수를 모집할 예정이라고 하니, 1기 모집과정이 궁금하신 분들은 &lt;a href=&quot;https://tosspublic.notion.site/Learner-s-High-1-145714bbfde78045922ef940cd16a04b&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;&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;저는 글또 커뮤니티에서 활동하고 있는데, 우연찮게도~? 글또의 백엔드 개발자분들 중에서도 토스 러너스 하이에 참여하시는 분들이 계셨습니다. 글또에서는 총 23분이 참여하신걸 확인했습니다. 저는 바로 노션 팀 페이지를 만들고 함께 달릴분들을 모집했고 결과적으로는 9분과 함께 서로의 작업물을 공유하며 한 달간 열심히 달렸습니다.(개인정보 부분은 모자이크 처리..)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1162&quot; data-origin-height=&quot;1324&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b4HVsI/btsMcswH9m6/B1gImBSitKchf6szbYEABK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b4HVsI/btsMcswH9m6/B1gImBSitKchf6szbYEABK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b4HVsI/btsMcswH9m6/B1gImBSitKchf6szbYEABK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb4HVsI%2FbtsMcswH9m6%2FB1gImBSitKchf6szbYEABK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;526&quot; height=&quot;599&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1162&quot; data-origin-height=&quot;1324&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-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;한 달간의 여정 시작!&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;토스 러너스하이에 참여하며 처음 고민했던 것은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;b&gt;팀과 회사에 어떤 이득을 가져다줄 것인가?&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;였습니다. 우리에게 남겨진&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;b&gt;기술 부채나 고질적인 문제는 무엇일까?&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;부터 고민해볼 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;러너스하이 교육은 자율적으로 진행되었기 때문에, 각자 회사에서 자율적으로 어떤 결과물을 만들지 정한 뒤 열심히 달려야 했습니다!! 하지만 아무래도 연말이다 보니 본업무들이 바빠서 아쉽게 목표했던 결과물을 수행하지 못하시는 분들도 있어 안타까웠습니다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 아래와 같은 방식으로 계획했던 목표를 달성할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;754&quot; data-origin-height=&quot;970&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cFU84O/btsMeznpaVA/dMKfbhYcGf4fmqPrWONkt1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cFU84O/btsMeznpaVA/dMKfbhYcGf4fmqPrWONkt1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cFU84O/btsMeznpaVA/dMKfbhYcGf4fmqPrWONkt1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcFU84O%2FbtsMeznpaVA%2FdMKfbhYcGf4fmqPrWONkt1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;462&quot; height=&quot;594&quot; data-origin-width=&quot;754&quot; data-origin-height=&quot;970&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;해결한 과제들&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;결과적으로 저는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;무중단 배포&lt;/b&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;b&gt;DLQ 적용&lt;/b&gt;&lt;/span&gt;&lt;span&gt;, 그리고 &lt;/span&gt;&lt;span&gt;&lt;b&gt;SAGA 패턴 도입&lt;/b&gt;&lt;/span&gt;&lt;span&gt;을 진행했습니다. 이를 통해 서비스 안정성과 장애 대응 능력을 강화하는 데 기여할 수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;다만 &lt;/span&gt;&lt;span&gt;&lt;b&gt;ELK 로깅 고도화&lt;/b&gt;&lt;/span&gt;&lt;span&gt;와 &lt;/span&gt;&lt;span&gt;&lt;b&gt;카테고리 코어 이슈 분석&lt;/b&gt;&lt;/span&gt;&lt;span&gt;은 시간이 부족해 깊게 다루지 못한 점이 아쉬웠습니다. 또한, 사내에서 외부 솔루션 및 조직도 연동과 같은 중요한 작업이 있었기에 일정 조율이 쉽지 않기도 했습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;추가적으로 엘라스틱서치&amp;nbsp;&lt;/span&gt;&lt;span&gt;&lt;b&gt;검색 엔진 최적화 및 동의어 처리 &lt;/b&gt;작업도&lt;/span&gt;&lt;span&gt;&amp;nbsp;수행했지만 메인 담당자는 따로 있었기에 개인적으로 만족스러울 만큼 기여하지는 못했다고 느꼈습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;하지만 앞선 과정을 통해 정해진 기간내에 목표를 지속적으로 상기시키며&lt;/span&gt;&lt;span&gt; 다양한 도전과 결과물을 만들&lt;/span&gt;&lt;span&gt;&amp;nbsp;수 있었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;과정 종료&lt;/span&gt;&lt;/h3&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;드디어 1월 16일이라는 공식적인 종료일이 왔습니다!!&lt;/span&gt;&lt;span&gt; 하지만 여기서 끝이 아니라 1월 31일까지 &lt;/span&gt;&lt;span&gt;토스 러너스하이 경험을 기반으로 경력 기술서를 제출&lt;/span&gt;&lt;span&gt;하면 다음과 같은 혜택이 주어졌습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #222222; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;혜택 1:&lt;/b&gt; 토스 Server Developer로의 채용 기회 부여 (직무 인터뷰)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;혜택 2:&lt;/b&gt; 멘토와의 캐주얼챗 제안&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;혜택 3:&lt;/b&gt; 토스커뮤니티 채용 포지션 추천&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;다만 경력 기술서를 제출하지 않아도 불이익은 없습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;배운 점 &quot;왜&quot;와 &quot;어떻게&quot;가 중요한 이유&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;토스 러너스하이를 통해 &lt;/span&gt;&lt;span&gt;개발자란 호기심이 많아야 하며 개발에서 &quot;&lt;b&gt;왜&lt;/b&gt;&quot;와 &quot;&lt;b&gt;어떻게&lt;/b&gt;&quot;가 얼마나 중요한지&lt;/span&gt;&lt;span&gt;를 다시 한번 느꼈습니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-spread=&quot;false&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;왜&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 해당 기술을 적용해야 하는가?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;왜&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 이 방법을 선택했는가?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;왜&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 문제가 발생했는가?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;어떻게&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 해결할 것인가?&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;b&gt;어떻게&lt;/b&gt;&lt;/span&gt;&lt;span&gt; 성장할 것인가?&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;앞선 질문을 끊임없이 던지며 고민하는 것이 잘하는&lt;/span&gt;&lt;span&gt;&amp;nbsp;개발자로 성장하는 길&lt;/span&gt;&lt;span&gt;이라고 느꼈습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;개발자는 &quot;결과&quot;를 만들어내는 사람&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;백엔드 개발자 3년 차에 접어들면서 &lt;/span&gt;&lt;span&gt;개발자는 과정보다 &quot;결과&quot;를 만들어내는 것이 중요하다&lt;/span&gt;&lt;span&gt;고 느끼고 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;토스러너스하이에서 배운 것 처럼&lt;/span&gt;&lt;span&gt; 깊이 고민하는 것도 중요하지만, &lt;/span&gt;&lt;span&gt;일단 부딪히고 행동하는 것이 더 큰 의미를 가질 때도 있다&lt;/span&gt;&lt;span&gt;는 걸 이번 경험을 통해 배웠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;토스 러너스하이를 통해 한 달 동안 의미 있는 시간을 보낼 수 있었습니다. 팀이나 회사에서 내가 기여할 수 있는 게 무엇이 있을까?? 와 같이 좀 더 주도적으로 업무를 깊게 생각하며 진행하다 보니 팀원들을 넘어서 결국에는 팀 전체의 생산성에 도움을 줄 수 있는 업무를 수행할 수 있었던 것 같습니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-pm-slice=&quot;1 1 []&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;추후 동일한 과정이 진행된다면, 더욱 발전한 모습으로 다시 참여하고 싶다는 생각을 했습니다. 앞으로도 주어진 환경에서 최대한으로 성장하면서 팀에게 조직에게 도움이 되는 방향은 어떤 것일까?라는 고민을 해볼 수 있을 것 같았습니다&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;러너스하이 기간 동안 수행한 업무를 정리했습니다. 깊게 다루지 못한 내용이나 기여를 많이 못했다고 느꼈던 부분은 제외시켰습니다.&lt;/p&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;DLQ 적용 및 이벤트 신뢰성 강화&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문제 상황&lt;/b&gt;&lt;/h3&gt;
&lt;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;수동 이벤트 재처리(isPublish 컬럼 활용)로 인한 운영 부담 증가&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주요 개선 사항&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;DLQ 기반 자동 복구 시스템 구축&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이벤트 실패 시 자동으로 DLQ로 이동 및 복구 프로세스 작동&lt;/li&gt;
&lt;li&gt;일시적 장애에 대한 즉시 재시도 로직 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;실시간 모니터링 체계 구축&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Grafana와 Slack 연동으로 장애 실시간 감지&lt;/li&gt;
&lt;li&gt;운영팀 즉시 대응 가능한 알림 시스템 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;선택 이유&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DLQ 기반 복구 기능을 도입하여 서비스 신뢰도를 높이고 운영 부담을 줄이기 위해서&lt;/li&gt;
&lt;li&gt;즉시 재시도 로직을 통해 일시적인 장애로 인한 이벤트 실패 최소화&lt;/li&gt;
&lt;li&gt;실시간 알림 시스템을 통해 장애를 빠르게 감지하고 대응&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;성과 및 결과&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;수동 재처리를 제거하여 운영 부담 감소 및 이벤트 신뢰성 강화&lt;/li&gt;
&lt;li&gt;실시간 장애 알림 연동을 통해 빠른 대처로 인한 고객 신뢰도 향상&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;향후 개선 방향&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DLQ 모니터링 강화를 통해 실시간 모니터링 및 장애 조기 감지를 목표로 할 예정입니다.&lt;/li&gt;
&lt;li&gt;지수 백오프를 적용하여 재시도 로직을 최적화할 예정입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;쿠버네티스 무중단 배포 체계 구축&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문제 상황&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;RollingUpdate 배포 방식을 적용하고 있었으나 서버의 크기가 커지면서 파드 재구동 시간이 길어져 서버 다운타임이 발생했고 서비스가 불안정해졌습니다.&lt;/li&gt;
&lt;li&gt;배포 시간을 공지하는 방법을 사용했으나 이로 인해 운영에 대한 부담이 증가하고 있었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주요 개선 사항&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;HealthCheck 도입&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;livenessProbe, readinessProbe 설정으로 무중단 배포 구현&lt;/li&gt;
&lt;li&gt;배포 중 트래픽 안정적 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;모니터링 시스템 구축&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Prometheus를 통한 리소스 모니터링 (CPU, 메모리, 트래픽)&lt;/li&gt;
&lt;li&gt;Grafana와 Slack 연동으로 실시간 알림 체계 구축&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;선택 이유&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;무중단 배포를 실현하면서 기존 배포 전략을 유지하기 위해 HealthCheck 방식을 선택&lt;/li&gt;
&lt;li&gt;Grafana &amp;amp; Slack 연동을 통해 장애 발생 시 즉각적인 대응이 가능하도록 구성&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;성과 및 결과&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;무중단 배포 구축 완료&lt;/li&gt;
&lt;li&gt;자동화된 장애 감지 및 대응 체계 구축을 통한 신속한 장애 대응&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;향후 개선 방향&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;헬스체크 로그 필터링을 통해 가독성을 개선할 예정입니다.&lt;/li&gt;
&lt;li&gt;서비스별 맞춤형 모니터링 대시보드를 추가적으로 구축하여 운영 효율성을 높일 계획입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;SAGA 패턴을 통한 분산 트랜잭션 관리&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;문제 상황&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;결제/재고 차감 등 이벤트 실패 시 데이터 정합성 문제 발생.&lt;/li&gt;
&lt;li&gt;분산된 도메인으로 인한 장애 원인 파악 지연&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주요 개선 사항&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Choreography 패턴 적용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 도메인별 독립적 트랜잭션 처리&lt;/li&gt;
&lt;li&gt;보상 트랜잭션으로 실패 시 자동 롤백&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;보상 트랜잭션 적용&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;결제 실패, 재고 차감 오류 등의 실패한 트랜잭션에 대해 롤백을 수행할 수 있도록 했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;데이터 일관성 보장&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Kafka 멱등성 설정으로 중복 처리 방지&lt;/li&gt;
&lt;li&gt;이벤트 기반 트랜잭션 처리 자동화&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;선택 이유&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도메인별로 event consumer가 존재하는 현 상황에서 각 서비스가 독립적으로 동작하면서도 트랜잭션을 관리할 수 있는 방법은 Choreography 패턴이라고 생각했습니다.&lt;/li&gt;
&lt;li&gt;보상 트랜잭션과 멱등성 적용을 통해 데이터 정합성을 유지하고, 장애 발생 시에도 안정적인 시스템 운영이 가능하도록 했습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;성과 및 결과&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;트랜잭션 일관성 유지 및 장애 복구 가능으로 시스템의 안정성을 크게 향상시켰습니다.&lt;/li&gt;
&lt;li&gt;서비스 간 느슨한 결합을 통해 유연한 트랜잭션 관리가 가능해졌습니다.&lt;/li&gt;
&lt;li&gt;장애 대응력 강화로 시스템의 복원력을 높였습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;향후 개선 방향&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;도메인별 최적화된 보상 트랜잭션과 에러 핸들링 전략을 구축할 예정입니다.&lt;/li&gt;
&lt;li&gt;멱등성 키를 활용하여 중복 메시지 처리를 더욱 정교하게 관리할 계획입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>활동</category>
      <category>1기</category>
      <category>글또</category>
      <category>러너스하이</category>
      <category>토스 러너스하이</category>
      <author>sjoongh</author>
      <guid isPermaLink="true">https://sjoongh.tistory.com/63</guid>
      <comments>https://sjoongh.tistory.com/entry/%ED%86%A0%EC%8A%A4-%EB%9F%AC%EB%84%88%EC%8A%A4%ED%95%98%EC%9D%B4-%EB%B0%B1%EC%97%94%EB%93%9C-%EA%B3%BC%EC%A0%95-%ED%9B%84%EA%B8%B0#entry63comment</comments>
      <pubDate>Mon, 10 Feb 2025 20:54:38 +0900</pubDate>
    </item>
    <item>
      <title>DLQ 적용기</title>
      <link>https://sjoongh.tistory.com/entry/DLQ-%EC%A0%81%EC%9A%A9%EA%B8%B0</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Dead Letter Queue (DLQ)란 무엇인가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DLQ는 정상적으로 처리되지 못한 메시지들을 저장하는 특별한 큐입니다.(카프카에서는 단순한 토픽입니다) DLQ의 본질은 특정 횟수 이상의 재시도 후에도 메시지 처리가 실패하거나 복구할 수 없는 오류가 발생했을 때 해당 메시지를 DLQ로 이동시켜 시스템이 계속 정상적으로 작동하면서 메시지를 손실하지 않고, 추후에 메시지를 검토하거나 재처리할 수 있도록 보장하는 방법입니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;DLQ가 필요한 이유&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 isPublish라는 컬럼을 이벤트 소싱 패턴에 적용시켜놔서 이벤트 발송 실패시 시스템 내부적으로 처리하고 있었습니다. 처리량과 실패율이 낮아 별도의 DLQ가 필요없어보였지만 솔루션 연동과 고객사들이 증가함에 따라 미리 예방하는 차원에서 현재 시점에서 미리 적용하는 것이 옳다고 판단했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 현재는 큰 이슈가 없는 케이스가 적은 이슈라도 프로젝트를 진행하며 실시간 배송 트래킹과 주문 처리시 데이터 손실이 되지 않는 것이 매우 중요하다고 생각했습니다. 데이터가 손실되거나 실시간으로 업데이트 되지 않을 경우 고객과의 신뢰도가 저하될 수 있다고 판단했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DLQ를 구축함으로서 메시지를 재시도하거나 분석할 수 있어 유지보수에 있어도 명확한 분석이 가능해졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 구축된 DLQ에 쌓인 메시지를 분석하면 반복적으로 발생하는 문제를 식별하고 시스템을 개선할 수 있습니다.&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;Dead Letter Queue 구현 방법&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 메시지 처리 로직&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1737184767568&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void processMessage(Message message) { 
	try { // 메시지 처리 비즈니스 로직 
    processBusinessLogic(message); 
    } 
    catch (Exception e) { 
    handleFailedMessage(message, e); 
    } 
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 코드에서 processBusinessLogic이 실패할 경우 메시지는 실패 처리기로 전달됩니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 실패한 메시지 처리&lt;/b&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1737195847454&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void handleFailedMessage(Message message, Exception e) { 
	if (message.getRetryCount() &amp;lt; MAX_RETRIES) { 
    	retryMessage(message); 
    } else { 
    	sendToDeadLetterQueue(message, e); 
        } 
    }&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 로직으로 메시지는 최대 재시도 횟수까지 재시도되며, 그 후에는 DLQ에 저장됩니다. 저는 10번을 재시도 하기로 결정했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. DLQ로 메시지 전송&lt;/b&gt;&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1737184812588&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void sendToDeadLetterQueue(Message message, Exception e) { 
	DLQMessage dlqMessage = new DLQMessage(message.getId(), message.getPayload(), e.getMessage(), LocalDateTime.now() ); 
    dlqQueue.add(dlqMessage); 
}​&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실패한 메시지와 오류 세부 정보와 함께 어떤 내용을 담고 있는지 또 어떤 에러 메시지가 발생했는지 등을 DLQ에 저장했습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;DLQ 적용시 유의할 점&lt;/h3&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;적절한 최대 재시도 횟수 설정&lt;/li&gt;
&lt;li&gt;지수 백오프 적용으로 시스템 부하 방지&lt;/li&gt;
&lt;li&gt;재시도 간격 설정 시 비즈니스 요구사항 고려&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모니터링 체계 구축
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DLQ 메시지 수 모니터링&lt;/li&gt;
&lt;li&gt;실패 원인 분석을 위한 로깅 강화&lt;/li&gt;
&lt;li&gt;이슈 발생시 slack에 알림 발송&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DLQ를 적용하는건 유의미한 결과를 낼 수 있었지만 만능은 아니라고 생각했습니다. 궁극적으로는 DLQ에 들어온 이벤트는 개발자가 직접 확인해 에러의 원인을 파악해 이슈를 해결해야하므로 에러 발생시 슬랙과 모니터링 도구와 연동해 즉각적으로 문제 상황을 파악할 수 있도록 구축했습니다.&lt;/p&gt;
&lt;p data-ke-size=&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;기존에는 고객 문의나 운영 부서의 검증 중에 데이터 정합성 문제가 발견되는 경우가 간혹 있었습니다. 실시간 배송 추적 시스템에 DLQ 도입 후에는 재시도 로직을 통해 자동으로 오류를 처리하고 실패한 이벤트는 DLQ에 로그로 기록되며 이슈 발생시 슬랙에 전송되어 즉각적인 대응이 가능해졌습니다. 이를 통해 유지보수의 효율성을 높이고 더욱 안정적인 서비스를 구축할 수 있었습니다.&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;DLQ 도입을 통해 얻은 교훈&lt;/h4&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA 프로젝트를 운영하다 보면 도메인 간 데이터 정합성 유지와 이슈 발생 시 원인을 파악하는 일이 중요합니다. 복잡한 시스템일수록 로그 관리와 공통 설정의 중요하다고 느꼈습니다.&lt;br /&gt;&lt;br /&gt;DLQ는 MSA 간 실시간 이벤트 처리에서 오류가 발생했을 때 효과적으로 대처할 수 있는 방법 중 하나로 이슈가 발생했을 때, 얼마나 자주 발생하는지, 원인은 무엇인지, 가장 적절한 대처 방법은 무엇인지 고민함으로써 최선의 해결책을 찾을 수 있다고 생각합니다.&lt;/p&gt;</description>
      <category>Spring</category>
      <category>DLQ</category>
      <category>Kafka</category>
      <category>MSA</category>
      <category>이벤트</category>
      <author>sjoongh</author>
      <guid isPermaLink="true">https://sjoongh.tistory.com/62</guid>
      <comments>https://sjoongh.tistory.com/entry/DLQ-%EC%A0%81%EC%9A%A9%EA%B8%B0#entry62comment</comments>
      <pubDate>Sat, 18 Jan 2025 19:41:37 +0900</pubDate>
    </item>
    <item>
      <title>잘하는 개발자란?</title>
      <link>https://sjoongh.tistory.com/entry/%EC%9E%98%ED%95%98%EB%8A%94-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%9E%80</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #0070d1; text-align: start;&quot; href=&quot;https://tosspublic.notion.site/Learner-s-High-1-145714bbfde78045922ef940cd16a04b&quot;&gt;토스 러너스 하이&lt;/a&gt;를 지원하며 받은 질문 중 잘하는 개발자란?'에 대해 깊이 고민해 보았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'잘하는 개발자란?' 너무나도 흥미로운 질문에 필자의 생각을 정리해 봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;DALL&amp;amp;middot;E 2024-12-20 08.45.33 - A visually engaging illustration representing the concept of a great developer. The image should include elements like a person coding at a desk with .webp&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPFbNq/btsLpiHXfWo/2uPhkm16ZbF7Vb4mDweTpk/img.webp&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPFbNq/btsLpiHXfWo/2uPhkm16ZbF7Vb4mDweTpk/img.webp&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPFbNq/btsLpiHXfWo/2uPhkm16ZbF7Vb4mDweTpk/img.webp&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPFbNq%2FbtsLpiHXfWo%2F2uPhkm16ZbF7Vb4mDweTpk%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;361&quot; height=&quot;361&quot; data-filename=&quot;DALL&amp;middot;E 2024-12-20 08.45.33 - A visually engaging illustration representing the concept of a great developer. The image should include elements like a person coding at a desk with .webp&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;우선 '잘하다'라는 뜻은 무엇일까? 사전적 의미를 살펴보자.&lt;/b&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;/li&gt;
&lt;li&gt;익숙하고 능란하게 하다.&lt;/li&gt;
&lt;li&gt;평탄하고 만족하게 하다.&lt;/li&gt;
&lt;li&gt;버릇으로 자주 하다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇듯 '잘하다'의 뜻은 상황, 문제, 또는 일에 대한 통찰력과 분별력을 바탕으로 최선의 결과를 만들어내는 행위를 뜻한다. 이런 행위를 특정 분야에서&amp;nbsp;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;오랜 시간에 걸쳐 익히고 능숙해진 것은 전문성을 가졌다고 볼 수 있으며 이런&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;&amp;nbsp;전문성을 가진 사람을 전문가라고 부른다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 '잘하는 개발자'란 무엇인가? 단순히 맡은 일을 원활히 수행하고 가치 있는 결과물을 창출하는 사람일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과거의 나는 잘하는 개발자란 프로그래밍적 기술이 뛰어난 사람이라고 생각했다. 기술이 뛰어난 작업자는 더 많은 업무를 수행할 수 있고 그러한 작업을 통해 회사입장에서는 원하는 제품을 출시하고 트렌드에 맞게 서비스를 변형시켜 이윤을 창출해내는 비즈니스 구조라고 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 시간이 지날수록 무엇인가 석연치 않다는 것을 깨달았다. 우리는 회사 또는 팀프로젝트를 수행할 때 함께 일하고 싶은 사람 또는 잘하는 사람이 무조건적으로 지식이 많고 프로그래밍적 능력이 뛰어난 사람이 아닌 것을 경험했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&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;/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;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 외에도 잘하는 개발자를 정의하는 많은 역량이 있겠지만 필자가 생각하는 가장 중요한 역량 세 가지를 작성해 봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 성장에 대한 욕구가 있는가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자는 항상 성장에 대한 욕구가 있어야 한다. 이는 기술적 역량, 문제해결능력, 책임감의 성장까지 이어진다. 어제보다 발전한 나를 만들겠다는 성장 동력이 결국 우리를 나아가게 만들기 때문이다. '개발'이라는 단어 자체도 새로운 영역을 개척하고 발전시키는 과정이라는 의미를 가지고 있듯이 개발자에게 성장은 필수적이라고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 우리는 목표를 세우고 무언가를 다짐해도 초심과는 달리 열정적인 마음이 쉽게 사그라드는 것을 많이 경험하기도 했다. 운동이나 러닝을 할 때에도 빠르게 몰아붙이거나 스퍼트를 내버리면 근육통이 오거나 빠르게 지쳐버리는 것처럼 성장 또한 마찬가지라고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자도 '작심삼일' 이라는 말을 절실히 느낀 적 있었고 번아웃도 경험해 봤기에 어떻게 지속적으로 나아갈 수 있을지에 대한 고민했다. 고민끝에 얻은 결론은 아래에서 자세하게 얘기하겠다. 사람마다 성장동력을 유지시키기 위한 연료는 너무나도 제각각이기에 본인을 깊게 탐구해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 크게 세 가지 생각이 성장을 위한 원동력이 되고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;첫번째: 꿈&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 인생에서 이루고 싶은 하나의 큰 꿈이 있다. 그 꿈을 실현하기 위해 어떻게 나아가야 할지에 대해 늘 고민한다. 꿈이 크기에 구체적인 계획보다는 올바른 방향으로 꾸준히 나아가자고 다짐하며 하루를 보내고 있다. 큰 목표를 향해 나아가는 과정만으로도 좋은 원동력이 되고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;두 번째: 주변 환경과 사람들&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성실하게 하루를 보내며 자신의 영역에서 발전하고, 긍정적인 에너지를 나누며 선한 영향력을 행사하는 사람들을 볼 때마다 나 또한 남들에게 도움이 되는 사람이 되고 싶고 그런 사람이 되고 싶다는 생각을 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스스로를 쉽게 변화시키기 어렵다면 좋은 환경과 사람들 속에 자신을 놓아야 한다. 좋은 사람들과 어울리고 긍정적인 환경 속에서 생활하면 세상을 바라보는 시야도 자연스럽게 넓어지는 경험을 할 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;세 번째:&lt;span&gt;&amp;nbsp;삶에 대한 가치관&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;필자의 가치관을 얘기하자면 왜 이런 가치관을 가지게 되었는지 또한 어떠한 시선으로 세상을 바라보고 있는지에 대한 설명이 필요하기에 이에 대해 설명하고자 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;삶의 목적과 의미에 대한 고민&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세상에 태어난 것에 목적이 있을까? 삶의 의미는 무엇일까? 이런 고민을 깊이 했던 적이 있다. 필자는 과거에 왜 태어났는가에 대해 집중하며 살아갔었는데 고민의 끝은 '삶에는 의미도 목적이 없다'는 결론으로 이어졌다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;역사 속 위대한 위인이나 현재의 유명인들 조차 모두 언젠가는 같은 결말에 도달할 것이고 나의 세상이 끝나면 이 거대한 세상도 끝이나 마찬가지기에 그렇게 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 책을 읽으며 이러한 관념에서 벗어날 수 있었다. 책의 좋은 점 중 하나는 스스로 생각하기 힘든 것에 대해 다른 시야와 생각으로 접근해보며 스스로를 깊이 탐구하고 고찰할 수 있는 기회를 주는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 책을 읽으며 깨달은 것은 태어난 사실에 '왜'라는 질문을 던지는 것이 아니라 '어떻게 살아가야 하는가'라는 고민이 중요하다는 점이다. '왜'라는 이유에 집착하다 보면 결국에는 모든 것이 무의미하게 느껴질 뿐이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;인간의 호기심과 집착&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;사람은 본질적으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;모든 것을&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이해하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;싶어 하고&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;통제하고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;싶어 한다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;모든 사물과 현상에 이름을 붙이고 의미를 부여하는 것도 이러한 것들 때문이다. 어쩌면 모든 자연현상과 우리가 살아가는 이 세상과 우주도 아무런 의미가&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;없을 수&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;있다. 인간은 세상을 명확하게 지각하기 위해서 현재를 살아가기 위해서 미래를 예측하기 위해서 다양한 이유로 의미를 부여한다. 물론 이는 타인과 소통하기 위한 도구이기도 하고 자신이 이해하지 못하는 것을&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;풀어헤치고&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;싶어 하는&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: left;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;호기심 때문이기도 하다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인간은 알 수 없는 것에 대해 두려움을 느끼면서 동시에 그것을 이해하고자 노력한다. 마치 어둠속에 무엇이 있는 것 인지 판도라의 상자 안에 무엇이 들어 있는지 확인하고자 하는 것과 같다. &lt;br /&gt;&lt;br /&gt;그러나 풀어내기 힘들고 정답이 없는 문제에 대해, 그저 존재하는 것에 대해 지나치게 몰입하여 '왜 태어났는가' 혹은 '우주는 왜 언젠가는 소멸하는가'와 같은 질문에 집착하게 되면 의미를 찾으려는 과정이 과한 이념으로 변질되어 부정적인 감정과 현상이 생기기 마련이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;집착에서 벗어난 삶&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 호기심을 무조건적으로 경계하라는 것은 아니다. 탐구는 장려하지만 그것에 집착하거나 얶매이지 않는 것이 중요하다. 이는 불교적인 사상과도 유사하다. 불교에서는 마음을 괴롭게 하고 현혹시키는 모든 작용을 번뇌라고 한다. 자신을 관철하고 관망하며 욕망이나 집착으로 인해 괴로움을 겪지 않는 것이 부처로 가는 길이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 무교이지만 불교의 도리를 기반으로 '왜 태어났는가'라는 질문의 수렁에서 벗어나 객관적으로 스스로를 살펴보며 긍정적인 방향으로 자신을 이끌 수 있었다. 이제 남은 고민은 어떻게 사는 것이 의미 있는 삶인가?이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;욕심은 번뇌를 만든다는 말이 있지만, 필자는 꿈을 이루기 위해 욕심을 온전히 버리지 않았다. 대신 내 욕심을 긍정적인 방향으로 변화시켜 주변 사람들에게 선한 영향력을 발휘하는 삶을 지향하기로 결정했고 고민에 대한 결론을 얻을 수 있었다. 이러한 다짐은 필자가 좋아하는 작가 알베르 카뮈의 부조리한 삶의 철학에도 영감을 받았다.&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/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://www.youtube.com/watch?v=oBIo2AyjNMo&quot;&gt;[낙관적 허무주의]&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;https://www.youtube.com/watch?v=Inc3Q6gBV2A&quot;&gt;[부조리]&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카뮈는 죽음이라는 피할 수 없는 결말 속에서도 삶의 의미를 스스로 만들어가야 한다고 주장했다. 아이러니하게도 죽음이라는 결말이 정해져 있기에, 매 순간 최선을 다할 수 있는 것이다. 이러한 관점에서 필자는 내가 할 수 있는 일에 최선을 다하며, 동시에 다른 사람들에게 긍정적인 영향을 미칠 수 있는 삶을 살기 위해 더욱 노력할 수 있게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;여러분의 원동력은 무엇일까?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람마다 삶을 움직이는 원동력은 전부 다르다. 질투, 부러움, 분노, 슬픔, 압박감, 벗어나고 싶은 마음, 배움의 즐거움, 혹은 현재 상황이 너무 싫은 감정 등등 모두 강력한 원동력이 될 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;중요한 것은 이러한 감정들을 온전히 품고, 그것들을 자신의 삶을 나아가게 하는 연료로 삼아야 한다는 것이다. 감정에 휘둘리지 않고 주체적으로 삶을 이끌어가는 사람이 되어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;삶에 정답은 없다. &quot;이렇게 살아야 한다&quot;, &quot;이것은 옳다&quot;와 같은 기준조차도 시대적 상황과 환경에 따라 달라지며, 종종 모순적이기까지 하다. 법과 상식, 도덕성과 윤리 역시 상황과 문화에 따라 다르게 해석될 수 있는 여지가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사람은 자신이 익숙한 환경과 문화에 적응하기 때문에 다른 문화나 관점을 쉽게 배척하기도 한다. 하지만 이는 자라온 환경과 문화적 차이에서 비롯된 것일 뿐 진리나 정답을 의미하지는 않기에 타인에게 쉽게 휘둘려서는 안 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;많은 자기 개발서도 삶에는 정답과 사회적으로 성공할 수 있는 방법이 있는 것처럼 말한다. 하지만 다른 사람에게 유효한 정답이 나에게는 전혀 맞지 않을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타인의 인생을 무작정 따라가는 대신, 자신만의 정답을 찾기 위한 질문과 고민을 이어가는 것이 중요하다. 역사 속 위인들의 말, 유명 CEO나 철학가, 학자들의 조언조차도 당신의 상황에선 적합하지 않을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;타인의 말에 귀기울이지 말라는 이야기가 아니며 스스로를 가장 잘 아는 존재는 자신이기에 외부의 자극과 조언, 경험을 기반으로 스스로를 탐구해 자신에게 가장 알맞은 옷을 입는 것이 중요하다.&lt;/p&gt;
&lt;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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 자신이 싫어하는 일은 정말 좋은 원동력이 될 수 있다. 사람은 싫어하는 일을 통해 성장하기 때문이다. 매일 좋아하는 일만 하고 살 수는 없다. 아무리 좋아하는 일도 반복되면 쉽게 질리고 항상 재밌을 수는 없기 마련이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 &quot;좋아하는 것&quot;이라고 말할 때, 그것이 진정 좋아하는 것인지 깊이 있게 탐구할 필요가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 &quot;영화를 보는것을 좋아한다&quot;고 했을 때 다음과 같은 구체적인 질문들을 통해 이를 세분화해볼 수 있다.&lt;/p&gt;
&lt;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;p data-ke-size=&quot;size16&quot;&gt;이러한 세부적인 탐구 과정을 거치다 보면 자신도 깨닫지 못했던 좋아하는 점과 싫어하는 점이 명확히 구분될 것이다. 결과적으로 자신이 진정으로 선호하는 것이 무엇인지 더 정확하게 파악할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 일이던 좋아하는 일을 하기 위해서는 반드시 싫어하는 일을 해야 할 때가 있다. 예를 들어, 여행을 가기 위해 일을 해야 하고, 건강을 위해 운동이 싫더라도 매일 운동을 해야 하며 돈을 벌기 위해서는 열심히  일해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 싫어하는 일은 우리를 움직이게 하고 발전시킨다. 물론 싫어하는 일을 반드시 해야 한다는 것은 아니며 모든 경우에 적용되는 말이 아니기에 이를 대체하거나 피할 방법을 찾는 것 또한 현명한 선택이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 과거의 부정적인 경험이나 싫었던 일들에 대해서는 재평가할 필요가 있다. 기억은 시간이 지남에 따라 왜곡되기 쉽다. 그 일이 싫었던 것이 아니라 당시의 상황이나 다른 부정적인 감정 때문에 그렇게 느꼈을 가능성도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금의 당신과 과거의 당신은 많이 달라졌기에, 다시 시도해본다면 좋은 경험으로 남을 수도 있다. 부정적인 감정을 회피하지 말고 당당히 마주해 부딪힘으로써 어제보다 더 나은 자신을 만날 수 있을 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 협업 커뮤니케이션이 원활한가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1인 개발자의 경우에는 해당되지 않을 수 있다.(관련 경험이 없어 정확히 알지는 못한다..) 개발자란 직업은 생각보다 훨씬 많은 사람들과 소통이 필요한 직업이다. 이는 자기 PR 능력과도 밀접하게 연결된다. 학교든 직장이든 자신의 능력을 실제보다 적게 드러내는 사람과, 반대로 실제보다 더 많이 표출해내는 사람도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;말이란 자신의 역량을 얼마나 잘 표현할 수 있는지 그리고 타인에게 신뢰감을 어떻게 형성할 수 있는지를 결정하는 중대한 요소이다. 너무 과장되게 표현한다면 문제가 되겠지만 자신을 솔직하게 잘 표현해내는 것도 중요한 자질 중 하나이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 뜻을 전달하더라도 어떤 방식으로 말하느냐에 따라 협업이 효율적으로 진행될 수도 있고, 반대로 서로 감정이 상하고 의견이 공유되지 않아 만족스럽지 못한 결과물을 만들 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'말 한마디에 천냥 빚을 갚는다' 라는 속담은 정말 뜻 깊다. 말은 한 번 내뱉으면 주워 담을 수도 없고 없던 일로 할 수도 없기에 신중해야 한다. 어떻게 표현하느냐에 따라 그 사람의 인품, 성격 더 나아가서는 생각의 깊이나 가치관을 엿볼 수 있다. 따라서 말을 잘하는 것, 즉 효과적으로 소통하는 능력은 매우 중요하며, 자신의 의견을 적극적으로 피력하는 태도도 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 업무 중 서로의 의견이 지나치게 일치하지 않는다면 어떻게 될까? 비즈니스적인 측면에서 본다면 똑같은 결과물을 만들기 위해 쓸모없는 시간을 낭비하고 있는 것이다. 이미 공통된 목표를 향해 나아가는 상황이기에 의견 차이가 발생했을 때 현재 상황에서 가장 효율적이고 자원을 낭비하지 않는 선택을 해야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현 상황에 최적화된 선택을 위해 미래를 고려하지 말라는 이야기는 아니다. 이런 이지선다의 상황에서 최선의 결정을 하고 선택하는 능력도 개발자의 역량을 보여주는 중요한 요소이다. 만약 잘못된 선택을 했다는 것을 깨닫게 되면, 이를 신속히 인정하고 문제를 수습하는 능력 역시 개발자로서 중요한 자질이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 소통이 어려운 점은 사람마다 스타일과 말투가 다르기 때문이다. 공과사를 철저히 구분하는 사람, 공과사의 경계에서 아슬아슬한 줄타기를 하는 사람, 또는 이를 자유롭게 넘나드는 사람 등 각양각색이며 원활하지 못한 소통은 자칫 오해를 쉽게 사기에 주의해야한다. 이렇듯 다양한 사람들과 소통해야 하기에 구성원들과 함께 노력해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인적으로는 팀원들끼리 친밀감을 쌓고, 때로는 사적인 이야기도 공유할 수 있는 관계여야 자유롭게 의견을 나누고 원활한 비즈니스를 만드는 데 도움이 된다고 생각한다. 결국 사람마다 선호하는 스타일과 호감의 기준이 다르기 때문에 개인차가 생길수밖에 없다. 올바른 협업을 위해서는 상대방과 나 모두 소통할 준비가 되어 있어야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 개발자로서 이루고 싶은 목표가 있는가?&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자의 목표설정은 정말 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;치킨집이나 차려야겠다..&quot;와 &quot;개발자로 40년을 일해야겠다&quot; 는 마음가짐에는 큰 차이가 있을 수밖에 없다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;큰 목표를 세우는 것도 좋지만 최대한 작게 시작하는 것이 훨씬 효과적이다. 한 달, 일주일 단위의 목표도 좋고 심지어 하루나 1시간 단위의 목표도 괜찮다. 목표가 작을수록 이루기 쉬우며 성취감을 빠르게 느낄 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;성공을 위한 방법은 무엇일까? 바로 그것에 대해 끊임없이 상기시키고 고민하는 것이다 자기개발서 책에서는 이를 극단적으로 활용해 매일 이루고 싶은 목표에 대해 끊임 없이 목표를 이룬 자신의 모습을 이미지 트레이닝을 하라고 하기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목표를 이룬 자신의 모습을 생생히 떠올리고, 그때의 기쁨, 행동 그리고 주변 사람들의 반응까지 구체적으로 이미지 트레이닝하라는 것이다. 이는 파일럿들이 전투기 탑승 전 훈련으로도 활용하는 방법이며 스포츠 선수들도 많이 사용하는 과학적인 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 앞서 설명한 삶을 살아갈 의미를 개발자라는 직업에서도 이룰 수 있다고 생각했다. 개발자라는 직업에 전념 한다면 선한 영향력을 행사하고 타인에게 도움이 되는 무언가를 만들 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대다수의 직업들이 타인을 위해 선한 영향력을 행사할 수 있지만 개발자가 재미있는건 이 세상에 존재하지 않는 새로운것을 창조해 불특정 다수에게 긍정적인 영향을 미칠 수 있다는 것이다. 정말 매력적이다. 이처럼 각  분야의 전문가들은 세상에 없던 새로운 무언가를 창조하거나 자신의 전문 분야를 깊이 탐구하여 인류의 지식 반경을 넓히는 데 기여한다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 생각을 바탕으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;필자는 &quot;개발자로서 어떻게 성장할 것인가?&quot;에 대해 꾸준히 고민하고 있다. 이를 위해서는 넓은 전문지식을 기반으로 타인에게 모범을 보이고 다방면으로 성장을 이루어내야 나의 꿈에 더욱 가까워질 것이고 목표를 이루기 쉬울 것이라고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발자의 목표는 다양할 수 있으며, 이루는 방법 또한 사람마다 다르다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;작은 목표라도 설정해 꾸준히 실천하면 좋다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;때로는 목표 없이 하루하루 최선을 다하다 보면 새로운 목표가 생길 수도 있고 목표가 없더라도 나도 모르게 타인에게 좋은 귀감이 될 수 있는 것이다. 방송인 유재석 님 역시 방송을 처음에는 별다른 목표 없이 시작했고 지금도 목표가 없는것이 목표라고 하셨지만 모두에게 모범이 되는 위치에 있는것처럼 말이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러분들은  개발자로서의 목표가 있는가? 삶의 목표는? 그렇지 않다면 하루하루 최선을 다 하고 있는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;결론적으로, 잘하는 개발자란 무엇일까?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;잘하는 개발자란? 라는 질문을 깊게 탐구하며 고찰해 보았다. 어떤 관점에서 바라보느냐 또는 어떤 상황에서 물어보느냐 누구에게 물어보느냐에 따라 답이 전부 달라질 수 있다. 하지만 필자가 생각하는 잘하는 개발자란 결국&lt;b&gt;&amp;nbsp;함께 일하고 싶은 사람&lt;/b&gt;, &lt;b&gt;타인에게&amp;nbsp;모범이 되며 존경받는 개발자&lt;/b&gt;라고 정의할 수 있을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;TMI&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;러너스 하이는 신청 후 합격했고 과정 진행중에 있다. 교육은 1월 16일날 종료되어 종료 이후에 후기 글을 작성할 예정이다.&lt;/p&gt;</description>
      <category>기타</category>
      <category>잘하는 개발자</category>
      <category>토스 러너스하이</category>
      <author>sjoongh</author>
      <guid isPermaLink="true">https://sjoongh.tistory.com/60</guid>
      <comments>https://sjoongh.tistory.com/entry/%EC%9E%98%ED%95%98%EB%8A%94-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%9E%80#entry60comment</comments>
      <pubDate>Thu, 19 Dec 2024 17:42:40 +0900</pubDate>
    </item>
    <item>
      <title>[2024] Google Cloud Study Jam 신청</title>
      <link>https://sjoongh.tistory.com/entry/2024-Google-Cloud-Study-Jam%EC%9D%84-%EC%8B%A0%EC%B2%AD%ED%95%98%EB%A9%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글 클라우드에서 교육을 하고 있는 것을 처음 알게된 것은 geekNews이었다. 정보를 찾아보다 구글 클라우드 교육이 있기에 재밌어보여 신청하게 됐다.(나만 빼고 이런 재밌는걸?..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;스크린샷 2024-12-19 오전 9.04.34.png&quot; data-origin-width=&quot;1893&quot; data-origin-height=&quot;828&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mQZfl/btsLmPzvKPj/KQHmkakMdQgMlmK7ezCAhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mQZfl/btsLmPzvKPj/KQHmkakMdQgMlmK7ezCAhK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mQZfl/btsLmPzvKPj/KQHmkakMdQgMlmK7ezCAhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmQZfl%2FbtsLmPzvKPj%2FKQHmkakMdQgMlmK7ezCAhK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1893&quot; height=&quot;828&quot; data-filename=&quot;스크린샷 2024-12-19 오전 9.04.34.png&quot; data-origin-width=&quot;1893&quot; data-origin-height=&quot;828&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필자는 머신러닝을 한번쯤은 공부해보고 싶었기 때문에 정말 좋은 기회라고 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 AI란 무엇인가에 대한 간단한 개념을 알려줬다. 생성형 AI, 머신러닝, 딥러닝, 프롬포트, LLM 전부 익숙한 단어들이지만 해당 개념들의 동작원리에 대해서는 탐구해본적이 없었기에 재밌었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 과정은 온라인 강의 시청과 직접 수행하는 과제로 이루어져 있는 것 같았다.&lt;/p&gt;
&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: #3c4043;&quot;&gt;총 25개의 학습자료가 있으며, 완료시간은 약&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #3c4043;&quot;&gt;50&lt;/span&gt;&lt;span style=&quot;color: #3c4043;&quot;&gt;시간입니다.&lt;/span&gt;&lt;span style=&quot;color: #3c4043;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #3c4043;&quot;&gt;다음을 포함하여 Google Cloud 플랫폼에서 생성 AI의 최신 기술과 서비스를 배웁니다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #212121;&quot;&gt;&lt;span style=&quot;color: #3c4043;&quot;&gt;생성적 AI 기초 및 애플리케이션 개발&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;color: #212121;&quot;&gt;&lt;span style=&quot;color: #3c4043;&quot;&gt;Gemini 플랫폼 전문 지식 및 다기능 애플리케이션&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;color: #212121;&quot;&gt;&lt;span style=&quot;color: #3c4043;&quot;&gt;책임 있는 AI의 원칙과 실천&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;color: #212121;&quot;&gt;&lt;span style=&quot;color: #3c4043;&quot;&gt;이미지 생성, 벡터 검색 및 MLOps&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;수료 코스 이외에도 구글 클라우드에는 클라우드와 AI에 대한 다양한 강의들이 있어  빠르게 코스 수료 후 클라우드 교육을 꼭 들어보고 싶었다! 필자는 회사내부에서 쿠버네티스를 사용하고 있는데 깊고 넓은 이해가 필요했다ㅠ 구글 클라우드에서 꼭 도움을 받아야겠다고 생각했다.(개념, 구글은 어떻게 사용하고 있는지, 유지보수 법 등등..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 한국어를 지원하지 않고 주피터를 처음 사용해보는 탓에 처음에는 학습에 난항을 겪고 있지만 어찌저찌 할 수 있을 것 같다.. 다행히 파이썬은 좀 사용해봐서 언어에 대한 거부감은 없었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기간은 12월 6일 ~ 1월 6일 까지 한 달 과정이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2025년에도 이런 재미있는 교육이 있으면 언제든지 들을 예정이다 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1월달에는 후기를 작성해야겠다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아 참고로 아직은 신청이 가능한것 같다 : &lt;a href=&quot;https://sites.google.com/view/2024-study-jams/ai-integration-class&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://sites.google.com/view/2024-study-jams/ai-integration-class&lt;/a&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc; color: #000000; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #212121;&quot;&gt;&lt;span&gt;참가자 모집기간&lt;/span&gt;&lt;span&gt;:&amp;nbsp; 온라인 자가 학습이므로 언제든 스터디 잼에 참여하여 학습 및 수료 가능합니다.&amp;nbsp;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;color: #212121;&quot;&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1차) ~ 2024년&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;월&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;6&lt;/span&gt;&lt;span&gt;일 오전&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;시까지&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;color: #212121;&quot;&gt;&lt;span&gt;(2차) ~ 2024년&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;월&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;13&lt;/span&gt;&lt;span&gt;일 오전&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;시까지&lt;/span&gt;&lt;/li&gt;
&lt;li style=&quot;color: #212121;&quot;&gt;&lt;span&gt;(3차) ~ 2024년&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;12&lt;/span&gt;&lt;span&gt;월&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;20&lt;/span&gt;&lt;span&gt;일 오전&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;9&lt;/span&gt;&lt;span&gt;시까지&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>활동</category>
      <category>AI</category>
      <category>Google Cloud</category>
      <category>llm</category>
      <category>study jam</category>
      <category>교육</category>
      <category>구글 클라우드 스터디잼</category>
      <category>머신러닝</category>
      <category>스터디잼</category>
      <author>sjoongh</author>
      <guid isPermaLink="true">https://sjoongh.tistory.com/59</guid>
      <comments>https://sjoongh.tistory.com/entry/2024-Google-Cloud-Study-Jam%EC%9D%84-%EC%8B%A0%EC%B2%AD%ED%95%98%EB%A9%B0#entry59comment</comments>
      <pubDate>Thu, 19 Dec 2024 09:23:10 +0900</pubDate>
    </item>
    <item>
      <title>JSON 직렬화가 왜 안돼?..</title>
      <link>https://sjoongh.tistory.com/entry/JSON-%EC%A7%81%EB%A0%AC%ED%99%94%EA%B0%80-%EC%99%9C-%EC%95%88%EB%8F%BC</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;개요&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;A서버에서 B서버로 body를 전달해주는 테스트를 하던 도중 필드 하나가 미전달 되는 현상이 지속적으로 발생했습니다. 해당 이슈를 해결하기 위해 다방면으로 고민했던 과정과 해결방안을 작성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;해결과정&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dto는 아래와 구성했고 해당 객체를 body에 담아 전달해주는 로직을 작성하고 있었습니다. 여느때와 다름없는 작업이었지만 isDelete 필드만 전달 되지 않는 현상이 발생하고 있었습니다. 간단한 문제라고 생각했기에 큰 문제가 아니라고 생각했지만 고난의 시작이었습니다ㅠ..&lt;/p&gt;
&lt;pre id=&quot;code_1732421294215&quot; class=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;data class jacksonTest(
    val id : String,
    val name : String,
    val isDelete : String,
    val createdAt : LocalDateTime
)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 봤을때는 아무런 문제도 없다고 생각했고 원인을 찾기 위해 다방면으로 시도해봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. body에 데이터가 안갈리가 없는데? 분명 담고 있고 request시에는 잘 들어감, 다른 필드들은 들어가는거보니 문제없음 또한 body값을 B서버에 전달했을때 200OK를 받은 상황&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;연동 문제 아님&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1-1. dto에서 값을 입력받을때 값 전달을 못받았나? controller 단에서는 값이 온전히 잘 들어오고 nullable처리도 안했기에 에러가 발생해야함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;필드 문제 아님&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1-2. B서버로 데이터가 전달되는 과정에서 문제가 있나? isDelete 필드만 제외시키는 설정이???&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;말도안됨&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1-3. 꿈을 꾸고 있나? -&lt;/span&gt;&lt;/span&gt;&lt;/s&gt;&lt;s&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;gt; 현실임&lt;/span&gt;&lt;/span&gt;&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. JSON 변환자체에 문제가 있는걸까? 라는 생각이 들어서 objectMapper를 사용해서 직접 값을 전달해봤습니다,&lt;/p&gt;
&lt;pre id=&quot;code_1732421989205&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val objectMapper = ObjectMapper().apply { 
propertyNamingStrategy = PropertyNamingStrategies.LOWER_CAMEL_CASE 
configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) 
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;똑같음.. -&amp;gt; &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;실패&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 필드명을 인식하지 못하는건가? 싶어 &lt;b&gt;@JsonProperty(&lt;span&gt;&quot;isDelete&quot;&lt;/span&gt;)&lt;/b&gt; 로 해당 필드를 명시시켜줬습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;실패&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4. request dto에 존재하는 다른 필드들에서 추가,수정,삭제를 시도해봤지만 isDelete 필드에서만 비슷한 현상이 발생했고ㅠ 다양한 방법으로 값을 전달하려고 시도했지만&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;-&amp;gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;전부 실패&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5. 그러다 isTest라는 필드를 만들어서 테스트 해보던중? 오?? isTest 필드도 전달하지 못하는 상황이 발생했습니다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;is로 시작하는 네이밍에 문제가 있나??... 그동안은 잘 사용하고 있었는데.. 이상한 생각이 들어 GPT에게 조언을 구해봤습니다. 다음과 같은 답변을 받을 수 있었습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;기본적으로 Jackson 라이브러리는 is로 시작하는 프로퍼티를 직렬화할 때 해당 필드를 getter로 간주하여 제외하는 경우가 있습니다.&lt;br /&gt;&lt;br /&gt;Kotlin의 data class에서 is로 시작하는 Boolean 타입 프로퍼티는 JSON 직렬화 시에 종종 문제를 일으킬 수 있습니다. 기본적으로 Jackson 라이브러리는 is로 시작하는 프로퍼티를 직렬화할 때 해당 필드를 getter로 간주하여 제외하는 경우가 있습니다. 그 결과, JSON 직렬화 시 예상치 못한 필드 이름 변경이 발생하거나 역직렬화 시 필드를 제대로 매핑하지 못하는 문제가 발생할 수 있습니다&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;답변을 받은 후 Jackson의 기본동작 원리가 궁금해 공식문서를 통해 찾아본결과 &lt;a title=&quot;이슈!&quot; href=&quot;https://github.com/FasterXML/jackson-module-kotlin/issues/80&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;gitHub에 동일한 이슈&lt;/a&gt;가 올라온것을 확인할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;의문점&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Bool타입에도 이슈가 발생할 수 있다는 것을 확인했지만 필자는 Bool타입으로 사용할때는 현재 이슈가 발생했던 경험은 없었으며 'is'로 시작하는 네이밍을 String타입으로 선언해서 사용하는것은 처음이였기에 해당 문제가 발생했다고 생각했고 Bool타입이 아닌 String이 문제가 될 수 있는지 공식문서를 통해 다음과 같은 자료를 찾을 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;b&gt;Jackson의 기본 동작: Jackson은 Java의 표준 getter 규칙을 따르며, is로 시작하는 메서드를 Boolean 타입의 getter로 취급합니다. 따라서, String타입의 필드 이름이 isSomething일 경우, Jackson은 이를 something으로 간주하여 JSON에 직렬화하거나 역직렬화를 시도합니다. 이로 인해 JSON과 객체 간의 매핑이 정확하지 않을 수 있습니다.&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아하.. 제가 선언했던 isDelete의 타입이 String이였기에 getter에서는 Delete로 변환하여 JSON 데이터로 직렬화하지 못했던 것이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 getter와는 달리 setter에서는 보통 문제가 발생하지 않습니다. JSON 역직렬화 시에는 ObjectMapper가 필드명으로 직접 매칭하기 때문입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;해결방법&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고생했던 원인과 해결방안을 확인했으니 getter 메소드를 직접 구현했습니다.&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot; style=&quot;background-color: #2b2b2b; color: #a9b7c6;&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;data class jacksonTest(
    val id : String,
    val name : String,
    val isDelete : String,
    val createdAt : LocalDateTime
)

fun getIsDelete(): String = isDelete&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;그동안 코틀린에서 data class와 jackson을 활용해 편리하게 사용하고 있어 몰랐지만 편리한 도구에는 숨겨진 동작과 원리가 있다는 것을 알았고 고생했던 문제였지만 이슈 발생시 다양한 검증과 기본지식이 탄탄해야 한다는 교훈을 다시 한번 얻었습니다. 해결하고 나니 재밌고 유익했습니다 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&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://github.com/FasterXML/jackson&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://github.com/FasterXML/jackson&lt;/a&gt;&lt;/p&gt;</description>
      <category>Kotlin</category>
      <category>Jackson</category>
      <category>JSON</category>
      <category>Kotlin</category>
      <category>직렬화</category>
      <author>sjoongh</author>
      <guid isPermaLink="true">https://sjoongh.tistory.com/58</guid>
      <comments>https://sjoongh.tistory.com/entry/JSON-%EC%A7%81%EB%A0%AC%ED%99%94%EA%B0%80-%EC%99%9C-%EC%95%88%EB%8F%BC#entry58comment</comments>
      <pubDate>Sun, 24 Nov 2024 13:49:41 +0900</pubDate>
    </item>
    <item>
      <title>undertow VS tomcat 비동기 처리(Feat.이벤트루프란?)</title>
      <link>https://sjoongh.tistory.com/entry/undertowNetty-VS-tomcat-%EB%8F%99%EC%9E%91-%EB%B9%84%EA%B5%90</link>
      <description>&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Undertow와 Tomcat의 비동기 처리&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Undertow&lt;/b&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Tomcat&lt;/b&gt;은 자바 기반 웹 서버인건 동일하지만 비동기 I/O 처리하는 방식은 다릅니다. 이 둘에 대한 차이점과 어떠한 원리로 동작 하는지 살펴보겠습니다. 설명을 드리기에 앞서 undertow에서 비동기 프로그래밍을 처리할때 중요한 개념인 이벤트 루프에 대해 소개하겠습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;이벤트 루프(Event Loop)란?&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이벤트 루프는 비동기 프로그래밍 모델에서 중요한 역할을 하는 개념으로 싱글 스레드 환경에서 비동기 처리를 지원하기 위해 사용됩니다. 이벤트를 큐에 넣고 큐에 있는 이벤트를 하나씩 처리하는 방식(콜스택&amp;amp;큐)으로 동작합니다. 이러한 이벤트 루프의 순환 과정을 통해 실시간으로 이벤트를 처리하며 동시성을 관리하고 효율적으로 자원을 사용할 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EtLFq/btsKC2yQsgO/fKHLFmK3GRPJLVL8Kfx7wK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EtLFq/btsKC2yQsgO/fKHLFmK3GRPJLVL8Kfx7wK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EtLFq/btsKC2yQsgO/fKHLFmK3GRPJLVL8Kfx7wK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEtLFq%2FbtsKC2yQsgO%2FfKHLFmK3GRPJLVL8Kfx7wK%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;506&quot; height=&quot;288&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Undertow의 이벤트 루프&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Undertow는 넷티(Netty)와 같은 비동기 I/O를 사용하고 있어 동일한 방식으로 이벤트 루프를 구현합니다. 하지만 Undertow는 필요에 따라 동기 방식으로 전환할 수 있어 Netty보다 유연하게 사용할 수 있습니다. 앞선 이유때문에 현업에서도 유용하게 사용하고 있습니다. Undertow의 주요 특징은 다음과 같습니다&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;비동기 I/O&lt;/b&gt;: Undertow는 비동기 I/O 모델을 사용하여 각 연결에 대한 요청과 응답을 비동기적으로 처리합니다. 이를 통해 블로킹 I/O의 문제를 피하고, 높은 동시성을 제공합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;멀티스레드 이벤트 루프&lt;/b&gt;: Undertow는 여러 개의 이벤트 루프 스레드를 사용하여 병렬로 작업을 처리합니다. 각 스레드는 큐에 있는 작업을 하나씩 처리하여 높은 처리량을 유지합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;커스터마이징 가능&lt;/b&gt;: Undertow는 사용자가 직접 이벤트 루프의 동작을 커스터마이징할 수 있도록 다양한 설정을 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Tomcat의 비동기처리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tomcat은 NIO (Non-blocking I/O) 커넥터를 통해 비동기 I/O를 지원합니다. Tomcat의 주요 특징은 다음과 같습니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;NIO 커넥터&lt;/b&gt;: Tomcat의 NIO 커넥터는 자바의 NIO 패키지를 사용하여 비동기 I/O를 처리합니다. 이를 통해 블로킹 I/O의 문제를 피하고, 많은 수의 동시 연결을 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;워크 스레드&lt;/b&gt;: Tomcat은 워크 스레드 풀을 사용하여 요청을 처리합니다. 각 스레드는 요청을 큐에서 가져와 처리하고, 처리 완료 후 다음 요청을 처리합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;NIO2와 APR&lt;/b&gt;: Tomcat은 NIO2와 APR(Apache Portable Runtime) 커넥터를 통해 더 높은 성능과 확장성을 제공합니다. 특히 APR 커넥터는 네이티브 라이브러리를 사용하여 성능을 극대화합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt; Undertow 의 이벤트 루프 동작&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Undertow는 Netty의 확장 버전이므로 Netty를 기준으로 설명드리겠습니다. Netty의 이벤트 루프 모델은 다음과 같은 특징을 가지고 있습니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;이벤트 루프 그룹&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Netty는 EventLoopGroup을 사용하여 이벤트 루프를 관리합니다. 이벤트 루프 그룹은 여러 이벤트 루프 스레드를 포함하며, 각 스레드는 이벤트를 처리하는 역할을 합니다.&lt;/li&gt;
&lt;li&gt;Netty의 이벤트 루프는 기본적으로 싱글스레드 모델을 따릅니다. 각 EventLoop는 하나의 스레드에서 실행되며, 여러 Channel(네트워크 연결)을 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;Netty는 일반적으로 두 가지 유형의 이벤트 루프 그룹을 사용합니다:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Boss Group&lt;/b&gt;: 클라이언트 연결 요청을 처리하고, 연결을 수락하는 역할을 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Worker Group&lt;/b&gt;: 실제 I/O 작업을 처리합니다. 각 연결에 대해 하나 이상의 이벤트 루프 스레드가 할당됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;채널과 파이프라인&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Netty의 Channel은 네트워크 연결을 나타내며, 각 채널은 하나의 이벤트 루프 스레드에 바인딩됩니다.&lt;/li&gt;
&lt;li&gt;각 Channel은 하나의 EventLoop에 바인딩됩니다. 이는 같은 EventLoop에 바인딩된 모든 Channel이 동일한 스레드에서 처리된다는 것을 의미합니다. 따라서 스레드 간의 컨텍스트 스위칭을 줄이고, 동기화 비용을 최소화할 수 있습니다.&lt;/li&gt;
&lt;li&gt;ChannelPipeline은 채널에 연결된 이벤트 처리 핸들러 체인입니다. 이벤트가 발생하면 파이프라인을 통해 순차적으로 핸들러가 호출됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이벤트 처리&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Netty는 이벤트를 비동기적으로 처리합니다. 이벤트는 이벤트 루프 스레드에 의해 큐에 추가되고, 스레드는 큐에서 이벤트를 하나씩 꺼내어 처리합니다.&lt;/li&gt;
&lt;li&gt;이벤트는 다양한 종류가 있습니다. 채널 등록, 데이터 읽기/쓰기, 예외 처리 등을 수행합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;558&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lnZKS/btsKD5anxBG/ihvXGvaQjZeXwYn0jzzMA1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lnZKS/btsKD5anxBG/ihvXGvaQjZeXwYn0jzzMA1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lnZKS/btsKD5anxBG/ihvXGvaQjZeXwYn0jzzMA1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlnZKS%2FbtsKD5anxBG%2FihvXGvaQjZeXwYn0jzzMA1%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;391&quot; height=&quot;370&quot; data-origin-width=&quot;590&quot; data-origin-height=&quot;558&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;이벤트 루프 동작&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Netty의 이벤트 루프는 기본적으로 싱글스레드 모델을 따릅니다. 각 EventLoop는 하나의 스레드에서 실행되며, 여러 Channel(네트워크 연결)을 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;각 Channel은 하나의 EventLoop에 바인딩됩니다. 이는 같은 EventLoop에 바인딩된 모든 Channel이 동일한 스레드에서 처리된다는 것을 의미합니다. 따라서 스레드 간의 컨텍스트 스위칭을 줄이고, 동기화 비용을 최소화할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;멀티스레드 이벤트 루프 그룹&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;EventLoopGroup은 여러 개의 EventLoop(각각 싱글스레드)를 포함하는 스레드 풀입니다. 이를 통해 Netty는 멀티스레드 환경에서도 효율적으로 동작할 수 있습니다.&lt;/li&gt;
&lt;li&gt;클라이언트 연결 요청은 Boss Group의 이벤트 루프에 의해 수락되고, 각 연결은 Worker Group의 이벤트 루프에 할당됩니다. 이렇게 하면 여러 스레드에서 동시에 I/O 작업을 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이벤트 루프 동작&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;싱글스레드 이벤트 루프&lt;/b&gt;: 각 EventLoop는 단일 스레드에서 실행되며, 여러 Channel을 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;멀티스레드 환경&lt;/b&gt;: EventLoopGroup은 여러 EventLoop를 포함할 수 있어, 멀티스레드 환경에서도 동작 가능합니다. 각 EventLoop는 단일 스레드로 실행되지만, 여러 EventLoop가 동시에 실행되어 여러 스레드를 사용할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;작업 분배&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Boss Group&lt;/b&gt;에서 클라이언트 연결 요청을 수락하고, 각 연결을 Worker Group의 EventLoop에 할당합니다.&lt;/li&gt;
&lt;li&gt;각 EventLoop는 할당된 Channel에서 발생하는 I/O 이벤트를 비동기적으로 처리합니다.&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Netty 동작 순서&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;이벤트 등록&lt;/b&gt;: 클라이언트 연결이 발생하면, Boss Group의 EventLoop가 이를 감지하고 새로운 Channel을 생성합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;채널 등록&lt;/b&gt;: 생성된 Channel은 Worker Group의 EventLoop에 등록됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이벤트 큐에 추가&lt;/b&gt;: 각 Channel에서 발생하는 I/O 이벤트는 해당 EventLoop의 이벤트 큐에 추가됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이벤트 처리&lt;/b&gt;: EventLoop는 큐에서 이벤트를 하나씩 꺼내어 처리하며 비동기적으로 I/O작업 및 비즈니스 로직 실행 등이 포함됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;콜백 실행&lt;/b&gt;: 처리 완료 후, 콜백 함수를 호출하여 결과를 반환하거나 후속 작업을 실행합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;반복&lt;/b&gt;: 이벤트 루프는 큐가 비어 있지 않은 한 계속해서 이벤트를 처리합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li style=&quot;list-style-type: none;&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Tomcat 서버 동작&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Tomcat 비동기 I/O를 사용하여 서블릿 요청을 처리할 수 있습니다. Tomcat의 비동기 처리 방식은 Undertow와는 약간 다릅니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;182&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nEANJ/btsKEtPDSQK/0NwyGxEx1eX3uC7uTp4s51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nEANJ/btsKEtPDSQK/0NwyGxEx1eX3uC7uTp4s51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nEANJ/btsKEtPDSQK/0NwyGxEx1eX3uC7uTp4s51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnEANJ%2FbtsKEtPDSQK%2F0NwyGxEx1eX3uC7uTp4s51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;862&quot; height=&quot;182&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;182&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&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;Tomcat의 NIO 커넥터는 비동기 I/O를 처리하기 위해 NIO 채널을 사용합니다. 커넥터는 클라이언트 연결을 수락하고, 요청을 프로세서에게 전달합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Acceptor&lt;/b&gt;: 클라이언트 연결을 수락하는 역할을 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Poller&lt;/b&gt;: 비동기 I/O 이벤트를 감지하고, 해당 이벤트를 처리하기 위해 워커 스레드에 할당합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;워크 스레드 풀&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Tomcat은 워크 스레드 풀을 사용하여 요청을 처리합니다. 요청이 들어오면, Poller는 워크 스레드 풀에서 사용 가능한 스레드를 가져와 요청을 처리합니다.&lt;/li&gt;
&lt;li&gt;워크 스레드는 요청을 처리하고 응답을 생성한 후, 다시 스레드 풀로 반환됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;서블릿 비동기 처리&lt;/b&gt;:
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Tomcat은 서블릿 3.0에서 도입된 비동기 서블릿 API를 지원합니다. 이를 통해 서블릿이 비동기적으로 요청을 처리할 수 있습니다.&lt;/li&gt;
&lt;li&gt;비동기 요청이 시작되면, 서블릿은 요청 처리를 다른 스레드로 넘기고, 메인 스레드는 즉시 반환됩니다. 요청 처리가 완료되면, 응답을 클라이언트에게 전송합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Tomcat 동작 순서&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;연결 수락&lt;/b&gt;: Acceptor 스레드가 클라이언트 연결을 수락합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이벤트 감지&lt;/b&gt;: Poller가 NIO 셀렉터를 사용하여 I/O 이벤트를 감지합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;이벤트 할당&lt;/b&gt;: 감지된 이벤트는 워크 스레드 풀에서 사용 가능한 스레드에 할당됩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;요청 처리&lt;/b&gt;: 워크 스레드는 할당된 요청을 처리하고, 처리 완료 후 스레드 풀로 반환됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;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: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;Undertow&lt;/b&gt; : EventLoopGroup의 설정은 Worker Thread의 수와 동작에 영향을 미칩니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Tomcat&lt;/b&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;&lt;b&gt;Undertow&lt;/b&gt; : 각 요청은 Channel과 연관되어 있으며 공통 메모리를 안전하게 공유할 수 있도록 설계됨&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Tomcat&lt;/b&gt;: 모든 워크 스레드가 JVM 메모리를 공유하여 객체나 데이터를 공유할 수 있지만 동기화 필요&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Undertow&lt;/b&gt;: Netty와 같은 비동기 I/O 라이브러리를 사용하고 소수의 스레드로 이벤트 루프에서 모든 요청을 비동기 처리하기에 자원 사용이 적고 동시성에 유리합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Tomcat&lt;/b&gt;: tomcat 또한 비동기 처리 방식을 구현할 수 있고 NIO 커넥터를 통해 비동기 I/O를 처리하며, NIO2와 APR 커넥터를 사용하여 더 높은 성능을 제공할 수 있습니다. 하지만 본질적으로는 동기 요청처리에 적합하며 비동기 작업에서는 Undertow에 비해 유연성이 낮습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;출처&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.programmersought.com/article/1699692284/#google_vignette&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://www.programmersought.com/article/1699692284/#google_vignette&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://livebook.manning.com/book/netty-in-action/chapter-7/24&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://livebook.manning.com/book/netty-in-action/chapter-7/24&lt;/a&gt;&lt;/p&gt;</description>
      <category>Spring</category>
      <category>Event loop</category>
      <category>netty</category>
      <category>tomcat</category>
      <category>undertow</category>
      <category>이벤트 루프</category>
      <author>sjoongh</author>
      <guid isPermaLink="true">https://sjoongh.tistory.com/57</guid>
      <comments>https://sjoongh.tistory.com/entry/undertowNetty-VS-tomcat-%EB%8F%99%EC%9E%91-%EB%B9%84%EA%B5%90#entry57comment</comments>
      <pubDate>Sat, 9 Nov 2024 21:36:59 +0900</pubDate>
    </item>
  </channel>
</rss>