<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>이것저것 개발기록</title>
    <link>https://ramka-devstory.tistory.com/</link>
    <description>개발하면서 있었던 일들을 기록하면서 공부하는 것을 목적으로 운영중입니다!</description>
    <language>ko</language>
    <pubDate>Sun, 21 Jun 2026 08:17:14 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Garam Kim</managingEditor>
    <item>
      <title>&amp;quot;전 세계 어디서든 빠르게&amp;quot; CDN(Content Delivery Network)의 원리</title>
      <link>https://ramka-devstory.tistory.com/51</link>
      <description>&lt;div class=&quot;post-container&quot; style=&quot;font-family: 'Pretendard', -apple-system, sans-serif; line-height: 1.8; color: #333; max-width: 800px; margin: 0 auto;&quot;&gt;
    &lt;p style=&quot;background: #f1f2f6; padding: 15px; border-left: 5px solid #2ecc71; font-style: italic;&quot; data-ke-size=&quot;size16&quot;&gt;
        &quot;미국에 있는 사용자가 한국 서버의 이미지를 보려면 왜 느릴까요?&quot; &lt;br /&gt;
        물리적 거리의 한계를 극복하고 사용자에게 가장 가까운 곳에서 콘텐츠를 전달하는 &lt;b&gt;CDN&lt;/b&gt;의 핵심 원리를 정리합니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #2c3e50; border-bottom: 2px solid #2c3e50; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;1. CDN이란 무엇인가?&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        CDN은 지리적으로 분산된 여러 서버의 네트워크입니다. 사용자가 웹사이트에 접속할 때, 메인 서버(Origin)까지 가지 않고 &lt;b&gt;가장 가까운 곳에 위치한 에지 서버(Edge Server)&lt;/b&gt;에서 캐싱된 데이터를 받아오게 함으로써 로딩 시간을 획기적으로 단축합니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #e67e22;&quot; data-ke-size=&quot;size26&quot;&gt;2. CDN의 주요 장점&lt;/h2&gt;
    &lt;div style=&quot;background: #fafafa; padding: 15px; border-radius: 8px; border: 1px solid #eee;&quot;&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px;&quot;&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;응답 시간 단축:&lt;/b&gt; 물리적 거리가 가까워지므로 레이턴시(Latency)가 줄어듭니다.&lt;/li&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;서버 부하 분산:&lt;/b&gt; 트래픽이 분산되어 메인 서버의 대역폭 비용과 CPU 부담을 줄여줍니다.&lt;/li&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;가용성 향상:&lt;/b&gt; 일부 에지 서버에 장애가 발생해도 다른 에지 서버가 서비스를 유지할 수 있습니다.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;h2 style=&quot;color: #2c3e50;&quot; data-ke-size=&quot;size26&quot;&gt;  실무 노트&lt;/h2&gt;
    &lt;div style=&quot;background: #fdf2f2; padding: 20px; border-radius: 8px; border-left: 5px solid #e74c3c;&quot;&gt;
        &lt;p style=&quot;margin-top: 0;&quot; data-ke-size=&quot;size16&quot;&gt;
            CDN은 정적 파일(이미지, JS, CSS, 영상)에 최적화되어 있습니다. 하지만 실무에서 가장 골치 아픈 점은 **'캐시 갱신(Cache Invalidation)'**입니다.
        &lt;/p&gt;
        &lt;p data-ke-size=&quot;size16&quot;&gt;
            &lt;b&gt;팁:&lt;/b&gt; 서버의 이미지를 교체했는데 사용자는 여전히 옛날 이미지를 보고 있다면 CDN 캐시가 남아있기 때문입니다. 이를 해결하기 위해 파일 이름 뒤에 해시값을 붙이는 &lt;b&gt;Versioning(예: logo.abcdef.png)&lt;/b&gt; 기법을 쓰거나, 수동으로 &lt;b&gt;Invalidation(무효화)&lt;/b&gt; 요청을 보내야 합니다. 다만, 전 세계 모든 에지 서버의 캐시를 비우는 데는 시간이 걸리고 비용이 발생할 수 있으므로, Versioning 방식을 가장 추천합니다.
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;blockquote style=&quot;text-align: center; font-weight: bold; margin-top: 30px; color: #2d3436;&quot;&gt;
        &quot;사용자와 가까울수록 속도는 빨라집니다. CDN은 그 거리를 좁히는 가장 영리한 방법입니다.&quot;
    &lt;/blockquote&gt;
&lt;/div&gt;</description>
      <category>IT 이야기</category>
      <category>CDN</category>
      <category>CloudFront</category>
      <category>CS</category>
      <category>네트워크</category>
      <category>성능최적화</category>
      <category>웹개발</category>
      <category>인프라</category>
      <author>Garam Kim</author>
      <guid isPermaLink="true">https://ramka-devstory.tistory.com/51</guid>
      <comments>https://ramka-devstory.tistory.com/51#entry51comment</comments>
      <pubDate>Sun, 11 Jan 2026 12:00:25 +0900</pubDate>
    </item>
    <item>
      <title>&amp;quot;JSON이 전부는 아니다?&amp;quot; 데이터 직렬화 포맷 3종 비교 (JSON, XML, Protobuf)</title>
      <link>https://ramka-devstory.tistory.com/50</link>
      <description>&lt;div class=&quot;post-container&quot; style=&quot;font-family: 'Pretendard', -apple-system, sans-serif; line-height: 1.8; color: #333; max-width: 800px; margin: 0 auto;&quot;&gt;
    &lt;p style=&quot;background: #f1f2f6; padding: 15px; border-left: 5px solid #e67e22; font-style: italic;&quot; data-ke-size=&quot;size16&quot;&gt;
        &quot;API 만들 때 무조건 JSON만 쓰시나요?&quot; &lt;br /&gt;
        현대 웹의 표준인 JSON부터 고전의 XML, 그리고 구글이 만든 고성능 Protobuf까지. 상황에 맞는 &lt;b&gt;데이터 직렬화 포맷&lt;/b&gt; 선택 가이드를 정리합니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #2c3e50; border-bottom: 2px solid #2c3e50; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;1. JSON (JavaScript Object Notation)&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        현재 가장 널리 쓰이는 포맷입니다. 사람이 읽기 쉽고(Human Readable), 대부분의 언어에서 지원하며 자바스크립트와의 호환성이 완벽합니다. 
    &lt;/p&gt;
    &lt;ul style=&quot;padding-left: 20px;&quot;&gt;
        &lt;li&gt;&lt;b&gt;장점:&lt;/b&gt; 가독성이 좋고 가볍습니다. 디버깅이 매우 쉽습니다.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;단점:&lt;/b&gt; 텍스트 기반이라 데이터 크기가 바이너리 포맷보다 큽니다. 데이터 타입이 단순합니다.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color: #2c3e50; border-bottom: 2px solid #2c3e50; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;2. XML (eXtensible Markup Language)&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        데이터를 태그로 감싸는 방식입니다. HTML과 유사하며 설정 파일이나 오래된 시스템(Legacy)에서 여전히 많이 보입니다.
    &lt;/p&gt;
    &lt;ul style=&quot;padding-left: 20px;&quot;&gt;
        &lt;li&gt;&lt;b&gt;장점:&lt;/b&gt; 스키마 정의(DTD, XSD)가 엄격하여 데이터 검증이 용이합니다.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;단점:&lt;/b&gt; 태그 때문에 데이터 용량이 매우 크고 파싱 속도가 느립니다.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color: #2c3e50; border-bottom: 2px solid #2c3e50; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;3. Protocol Buffers (Protobuf)&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        구글에서 개발한 바이너리 직렬화 포맷입니다. 텍스트가 아닌 이진 데이터로 전송됩니다.
    &lt;/p&gt;
    &lt;ul style=&quot;padding-left: 20px;&quot;&gt;
        &lt;li&gt;&lt;b&gt;장점:&lt;/b&gt; JSON보다 훨씬 작고 빠릅니다. 엄격한 타입 체크가 가능합니다.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;단점:&lt;/b&gt; 이진 데이터라 사람이 눈으로 읽을 수 없습니다. 전용 컴파일러가 필요합니다.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color: #2c3e50;&quot; data-ke-size=&quot;size26&quot;&gt;  실무 노트&lt;/h2&gt;
    &lt;div style=&quot;background: #f0f7ff; padding: 20px; border-radius: 8px; border-left: 5px solid #3498db;&quot;&gt;
        &lt;p style=&quot;margin-top: 0;&quot; data-ke-size=&quot;size16&quot;&gt;
            실무에서 무엇을 쓸지는 **'누가 이 데이터를 읽는가'**에 달려 있습니다.
        &lt;/p&gt;
        &lt;p data-ke-size=&quot;size16&quot;&gt;
            &lt;b&gt;팁:&lt;/b&gt; 일반적인 웹 서비스의 프론트엔드와 백엔드 통신에는 &lt;b&gt;JSON&lt;/b&gt;이 정답입니다. 생산성과 디버깅 편의성 때문이죠. 하지만 서버와 서버가 통신하는 **MSA(마이크로서비스 아키텍처)** 환경이나, 모바일 게임처럼 데이터 전송량을 극한으로 줄여야 하는 환경이라면 &lt;b&gt;Protobuf(gRPC)&lt;/b&gt; 도입을 적극 검토해야 합니다. JSON을 Protobuf로 바꾸는 것만으로도 네트워크 비용을 절반 이하로 줄일 수 있는 경우가 많습니다.
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;blockquote style=&quot;text-align: center; font-weight: bold; margin-top: 30px; color: #34495e;&quot;&gt;
        &quot;표준은 상황에 따라 변합니다. 도구의 특성을 알고 선택하는 것이 설계의 시작입니다.&quot;
    &lt;/blockquote&gt;
&lt;/div&gt;</description>
      <category>IT 이야기</category>
      <category>API</category>
      <category>grpc</category>
      <category>json</category>
      <category>Protobuf</category>
      <category>XML</category>
      <category>데이터직렬화</category>
      <category>백엔드</category>
      <category>웹개발</category>
      <author>Garam Kim</author>
      <guid isPermaLink="true">https://ramka-devstory.tistory.com/50</guid>
      <comments>https://ramka-devstory.tistory.com/50#entry50comment</comments>
      <pubDate>Sun, 11 Jan 2026 12:00:01 +0900</pubDate>
    </item>
    <item>
      <title>&amp;quot;서비스 중단 없는 업데이트&amp;quot; 무중단 배포 전략(Blue-Green, Rolling, Canary)</title>
      <link>https://ramka-devstory.tistory.com/48</link>
      <description>&lt;div class=&quot;post-container&quot; style=&quot;font-family: 'Pretendard', -apple-system, sans-serif; line-height: 1.8; color: #333; max-width: 800px; margin: 0 auto;&quot;&gt;
    &lt;p style=&quot;background: #f1f2f6; padding: 15px; border-left: 5px solid #0984e3; font-style: italic;&quot; data-ke-size=&quot;size16&quot;&gt;
        &quot;배포할 때마다 서버를 잠시 꺼야 할까요?&quot; &lt;br /&gt;
        사용자는 서비스가 업데이트되는 줄도 모르게, 조용하고 안전하게 새로운 버전을 반영하는 &lt;b&gt;무중단 배포&lt;/b&gt;의 세 가지 핵심 전략을 정리합니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #2c3e50; border-bottom: 2px solid #2c3e50; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;1. 롤링 배포 (Rolling Update)&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        가장 일반적인 방식입니다. 여러 대의 서버 중 일부를 순차적으로 새로운 버전으로 교체합니다. 
    &lt;/p&gt;
    &lt;ul style=&quot;padding-left: 20px;&quot;&gt;
        &lt;li&gt;&lt;b&gt;장점:&lt;/b&gt; 추가적인 서버 자원이 많이 필요하지 않습니다.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;단점:&lt;/b&gt; 배포 중에는 서버 대수가 줄어들어 부하가 집중될 수 있고, 구버전과 신버전이 공존하는 시간이 발생합니다.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color: #e67e22;&quot; data-ke-size=&quot;size26&quot;&gt;2. 블루-그린 배포 (Blue-Green Deployment)&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        구버전(Blue)과 동일한 수의 신버전(Green) 서버를 미리 다 띄워놓고, 로드밸런서를 통해 트래픽을 한 번에 전환합니다.
    &lt;/p&gt;
    &lt;ul style=&quot;padding-left: 20px;&quot;&gt;
        &lt;li&gt;&lt;b&gt;장점:&lt;/b&gt; 구버전/신버전 공존 문제가 없고, 문제 발생 시 즉시 롤백이 가능합니다.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;단점:&lt;/b&gt; 서버 자원이 정확히 두 배로 필요하여 비용 부담이 큽니다.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color: #e67e22;&quot; data-ke-size=&quot;size26&quot;&gt;3. 카나리 배포 (Canary Deployment)&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        광산의 카나리아처럼, 소수의 사용자에게만 먼저 신버전을 노출하여 테스트한 뒤 점진적으로 트래픽을 늘립니다.
    &lt;/p&gt;
    &lt;ul style=&quot;padding-left: 20px;&quot;&gt;
        &lt;li&gt;&lt;b&gt;장점:&lt;/b&gt; 실제 운영 환경에서 리스크를 최소화하며 성능과 오류를 검증할 수 있습니다.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;단점:&lt;/b&gt; 트래픽 제어 로직이 복잡해질 수 있습니다.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color: #2c3e50;&quot; data-ke-size=&quot;size26&quot;&gt;  실무 노트&lt;/h2&gt;
    &lt;div style=&quot;background: #f0f7ff; padding: 20px; border-radius: 8px; border-left: 5px solid #3498db;&quot;&gt;
        &lt;p style=&quot;margin-top: 0;&quot; data-ke-size=&quot;size16&quot;&gt;
            무중단 배포에서 개발자가 가장 고생하는 지점은 애플리케이션 코드가 아니라 &lt;b&gt;데이터베이스(DB)&lt;/b&gt;입니다.
        &lt;/p&gt;
        &lt;p data-ke-size=&quot;size16&quot;&gt;
            &lt;b&gt;팁:&lt;/b&gt; 서버는 신버전인데 DB 스키마가 아직 구버전이라면 에러가 나겠죠? 이를 해결하기 위해 DB 스키마 변경 시에는 &lt;b&gt;'하위 호환성'&lt;/b&gt;을 유지하며 배포하는 것이 철칙입니다. 컬럼 삭제 시에도 바로 지우지 않고, 1단계에서 새 컬럼 추가 및 데이터 마이그레이션, 2단계에서 신버전 배포, 3단계에서 구버전 컬럼 삭제라는 '단계적 배포' 프로세스를 몸에 익히는 것이 중요합니다.
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;blockquote style=&quot;text-align: center; font-weight: bold; margin-top: 30px; color: #34495e;&quot;&gt;
        &quot;완벽한 배포는 사용자가 배포 사실을 전혀 눈치채지 못하게 하는 것입니다.&quot;
    &lt;/blockquote&gt;
&lt;/div&gt;</description>
      <category>IT 이야기</category>
      <category>BLUEGREEN</category>
      <category>Canary</category>
      <category>CI/CD</category>
      <category>devops</category>
      <category>RollingUpdate</category>
      <category>무중단배포</category>
      <category>백엔드</category>
      <category>인프라</category>
      <author>Garam Kim</author>
      <guid isPermaLink="true">https://ramka-devstory.tistory.com/48</guid>
      <comments>https://ramka-devstory.tistory.com/48#entry48comment</comments>
      <pubDate>Sat, 10 Jan 2026 12:00:47 +0900</pubDate>
    </item>
    <item>
      <title>&amp;quot;이벤트 폭주를 막아라&amp;quot; 디바운싱(Debouncing)과 쓰로틀링(Throttling)</title>
      <link>https://ramka-devstory.tistory.com/49</link>
      <description>&lt;div class=&quot;post-container&quot; style=&quot;font-family: 'Pretendard', -apple-system, sans-serif; line-height: 1.8; color: #333; max-width: 800px; margin: 0 auto;&quot;&gt;
    &lt;p style=&quot;background: #f1f2f6; padding: 15px; border-left: 5px solid #2ecc71; font-style: italic;&quot; data-ke-size=&quot;size16&quot;&gt;
        &quot;검색창에 글자 하나 칠 때마다 API 요청이 가고 있나요?&quot; &lt;br /&gt;
        짧은 시간 동안 쏟아지는 수많은 이벤트를 제어하여 브라우저와 서버의 부하를 획기적으로 줄이는 두 가지 기법을 알아봅니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #2c3e50; border-bottom: 2px solid #2c3e50; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;1. 디바운싱 (Debouncing)&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        연이어 호출되는 함수들 중 &lt;b&gt;마지막 함수(또는 제일 처음 함수)&lt;/b&gt;만 호출하도록 하는 방식입니다. 주로 '입력이 멈춘 뒤' 실행되어야 하는 경우에 사용합니다.
    &lt;/p&gt;
    &lt;ul style=&quot;padding-left: 20px;&quot;&gt;
        &lt;li&gt;&lt;b&gt;적용 사례:&lt;/b&gt; 검색창 자동완성 (타이핑이 끝난 후 API 요청), 창 크기 조절(resize) 이벤트.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;핵심:&lt;/b&gt; &quot;계속 이벤트가 오면 무시하고, 마지막 이벤트 이후 n초가 지나면 그때 처리한다.&quot;&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color: #e67e22;&quot; data-ke-size=&quot;size26&quot;&gt;2. 쓰로틀링 (Throttling)&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        마지막 함수가 호출된 후 일정 시간이 지나기 전까지는 &lt;b&gt;다시 호출되지 않도록&lt;/b&gt; 하는 방식입니다. 즉, 일정 시간 간격으로 실행을 보장합니다.
    &lt;/p&gt;
    &lt;ul style=&quot;padding-left: 20px;&quot;&gt;
        &lt;li&gt;&lt;b&gt;적용 사례:&lt;/b&gt; 무한 스크롤(scroll) 이벤트, 클릭 중복 방지.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;핵심:&lt;/b&gt; &quot;아무리 이벤트가 많이 와도 n초에 한 번만 실행한다.&quot;&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color: #2c3e50;&quot; data-ke-size=&quot;size26&quot;&gt;  실무 노트&lt;/h2&gt;
    &lt;div style=&quot;background: #fdf2f2; padding: 20px; border-radius: 8px; border-left: 5px solid #e74c3c;&quot;&gt;
        &lt;p style=&quot;margin-top: 0;&quot; data-ke-size=&quot;size16&quot;&gt;
            이 두 기법은 라이브러리(Lodash 등)를 쓰면 한 줄로 해결되지만, 그 차이를 명확히 아는 것이 중요합니다. 
        &lt;/p&gt;
        &lt;p data-ke-size=&quot;size16&quot;&gt;
            &lt;b&gt;팁:&lt;/b&gt; 검색 기능에는 &lt;b&gt;디바운싱&lt;/b&gt;이 압도적으로 유리합니다. 만약 검색에 쓰로틀링을 쓰면 사용자가 '제미나이'라고 치는 동안 '제', '제미', '제미나이' 총 3번의 요청이 간격에 맞춰 갈 수 있지만, 디바운싱은 타자가 멈춘 후 '제미나이' 딱 한 번만 보내기 때문이죠. 반면 스크롤 이벤트처럼 데이터 로딩이 주기적으로 필요한 곳은 &lt;b&gt;쓰로틀링&lt;/b&gt;이 적합합니다. 상황에 맞는 적절한 도구 선택이 프론트엔드 성능 최적화의 첫걸음입니다.
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;blockquote style=&quot;text-align: center; font-weight: bold; margin-top: 30px; color: #2d3436;&quot;&gt;
        &quot;제어되지 않는 이벤트는 비용입니다. 효율적인 흐름 제어가 매끄러운 UX를 만듭니다.&quot;
    &lt;/blockquote&gt;
&lt;/div&gt;</description>
      <category>IT 이야기</category>
      <category>debounce</category>
      <category>js</category>
      <category>Throttle</category>
      <category>성능최적화</category>
      <category>웹개발</category>
      <category>자바스크립트</category>
      <category>프론트엔드</category>
      <author>Garam Kim</author>
      <guid isPermaLink="true">https://ramka-devstory.tistory.com/49</guid>
      <comments>https://ramka-devstory.tistory.com/49#entry49comment</comments>
      <pubDate>Sat, 10 Jan 2026 12:00:04 +0900</pubDate>
    </item>
    <item>
      <title>&amp;quot;npm은 이제 옛말?&amp;quot; pnpm과 yarn Berry가 사랑받는 이유</title>
      <link>https://ramka-devstory.tistory.com/47</link>
      <description>&lt;div class=&quot;post-container&quot; style=&quot;font-family: 'Pretendard', -apple-system, sans-serif; line-height: 1.8; color: #333; max-width: 800px; margin: 0 auto;&quot;&gt;
    &lt;p style=&quot;background: #f1f2f6; padding: 15px; border-left: 5px solid #2ecc71; font-style: italic;&quot; data-ke-size=&quot;size16&quot;&gt;
        &quot;node_modules 폴더가 왜 이렇게 무거운 걸까요?&quot; &lt;br /&gt;
        자바스크립트 생태계의 고질적인 문제인 패키지 관리. &lt;b&gt;npm, yarn, pnpm&lt;/b&gt;의 차이를 이해하고 내 프로젝트에 맞는 도구를 골라봅시다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #2c3e50; border-bottom: 2px solid #2c3e50; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;1. 패키지 매니저의 진화&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        처음에는 &lt;b&gt;npm&lt;/b&gt;이 독점했지만, 느린 속도와 보안 문제로 &lt;b&gt;yarn(Classic)&lt;/b&gt;이 등장했습니다. 이후 npm도 발전했지만, 여전히 거대한 &lt;code&gt;node_modules&lt;/code&gt;의 구조적 한계(유령 의존성 등)를 해결하기 위해 &lt;b&gt;pnpm&lt;/b&gt;과 &lt;b&gt;yarn Berry&lt;/b&gt;가 등장했습니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #e67e22;&quot; data-ke-size=&quot;size26&quot;&gt;2. pnpm의 마법: 심볼릭 링크(Symbolic Link)&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        pnpm은 같은 패키지를 여러 프로젝트에서 쓰더라도 &lt;b&gt;디스크에 딱 한 번만 저장&lt;/b&gt;합니다. 대신 각 프로젝트의 &lt;code&gt;node_modules&lt;/code&gt;에는 실제 파일이 아닌 하드 링크를 생성하죠. 덕분에 설치 속도가 압도적으로 빠르고 디스크 용량을 획기적으로 아낄 수 있습니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #2c3e50;&quot; data-ke-size=&quot;size26&quot;&gt;  실무 노트&lt;/h2&gt;
    &lt;div style=&quot;background: #fdf2f2; padding: 20px; border-radius: 8px; border-left: 5px solid #e74c3c;&quot;&gt;
        &lt;p style=&quot;margin-top: 0;&quot; data-ke-size=&quot;size16&quot;&gt;
            최근 많은 기업들이 &lt;b&gt;yarn Berry(v2 이상)&lt;/b&gt;의 &lt;b&gt;Zero-Install&lt;/b&gt; 정책을 도입하고 있습니다. 의존성 파일을 Git에 올려서 &lt;code&gt;npm install&lt;/code&gt; 과정 없이 바로 실행하게 만드는 기법이죠.
        &lt;/p&gt;
        &lt;p data-ke-size=&quot;size16&quot;&gt;
            &lt;b&gt;팁:&lt;/b&gt; 만약 대규모 모노레포(Monorepo) 구조를 고민 중이라면 &lt;b&gt;pnpm&lt;/b&gt;을 강력 추천합니다. 의존성 관리가 훨씬 엄격해서 &quot;내가 설치하지 않은 라이브러리를 몰래 가져다 쓰는&quot; 실수를 원천 차단해 줍니다. 반면, 가벼운 개인 프로젝트라면 가장 표준적인 &lt;b&gt;npm&lt;/b&gt;으로도 충분합니다. 도구를 고를 땐 유행보다 팀원들의 익숙함과 프로젝트의 규모를 먼저 고려해 보세요.
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;blockquote style=&quot;text-align: center; font-weight: bold; margin-top: 30px; color: #2d3436;&quot;&gt;
        &quot;도구의 차이를 아는 것이 효율적인 개발 환경 구축의 첫걸음입니다.&quot;
    &lt;/blockquote&gt;
&lt;/div&gt;</description>
      <category>IT 이야기</category>
      <category>javascript</category>
      <category>npm</category>
      <category>pnpm</category>
      <category>Yarn</category>
      <category>웹개발</category>
      <category>패키지매니저</category>
      <category>프론트엔드</category>
      <author>Garam Kim</author>
      <guid isPermaLink="true">https://ramka-devstory.tistory.com/47</guid>
      <comments>https://ramka-devstory.tistory.com/47#entry47comment</comments>
      <pubDate>Fri, 9 Jan 2026 12:00:32 +0900</pubDate>
    </item>
    <item>
      <title>&amp;quot;에러는 막는 것이 아니라 관리하는 것&amp;quot; 백엔드 예외 처리 전략</title>
      <link>https://ramka-devstory.tistory.com/46</link>
      <description>&lt;div class=&quot;post-container&quot; style=&quot;font-family: 'Pretendard', -apple-system, sans-serif; line-height: 1.8; color: #333; max-width: 800px; margin: 0 auto;&quot;&gt;
    &lt;p style=&quot;background: #f1f2f6; padding: 15px; border-left: 5px solid #e74c3c; font-style: italic;&quot; data-ke-size=&quot;size16&quot;&gt;
        &quot;서버가 죽지는 않았는데, 클라이언트는 왜 500 에러를 받을까요?&quot; &lt;br /&gt;
        사용자에게 친절하고 개발자에게는 명확한 디버깅 정보를 주는 &lt;b&gt;견고한 예외 처리 시스템&lt;/b&gt; 구축법을 정리합니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #2c3e50; border-bottom: 2px solid #2c3e50; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;1. Checked Exception vs Unchecked Exception&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        자바와 같은 언어에서는 예외를 두 가지로 나눕니다. 반드시 처리해야 하는 &lt;b&gt;Checked Exception&lt;/b&gt;과 런타임에 발생하는 &lt;b&gt;Unchecked Exception&lt;/b&gt;입니다. 현대적인 프로그래밍에서는 로직의 가독성을 위해 대부분의 예외를 런타임 예외로 감싸서(Wrapping) 던지는 추세입니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #e67e22;&quot; data-ke-size=&quot;size26&quot;&gt;2. 전역 예외 처리기(Global Exception Handler) 도입&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        컨트롤러마다 &lt;code&gt;try-catch&lt;/code&gt;를 도배하고 있지는 않으신가요? 이는 코드 중복을 초래하고 유지보수를 어렵게 만듭니다. 스프링의 &lt;code&gt;@RestControllerAdvice&lt;/code&gt;나 익스프레스의 에러 핸들링 미들웨어를 사용하여 &lt;b&gt;한 곳에서 예외를 공통적으로 처리&lt;/b&gt;해야 합니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #2c3e50;&quot; data-ke-size=&quot;size26&quot;&gt;  실무 노트&lt;/h2&gt;
    &lt;div style=&quot;background: #f0f7ff; padding: 20px; border-radius: 8px; border-left: 5px solid #3498db;&quot;&gt;
        &lt;p style=&quot;margin-top: 0;&quot; data-ke-size=&quot;size16&quot;&gt;
            실무에서 가장 나쁜 습관은 예외를 잡고 나서 &lt;b&gt;로그만 찍고 아무것도 안 하거나, 로그조차 남기지 않는 것&lt;/b&gt;입니다. 에러가 발생했다면 반드시 의미 있는 정보를 남겨야 합니다.
        &lt;/p&gt;
        &lt;p data-ke-size=&quot;size16&quot;&gt;
            &lt;b&gt;팁:&lt;/b&gt; 클라이언트에게는 &lt;code&gt;Internal Server Error&lt;/code&gt; 같은 모호한 메시지 대신, &lt;b&gt;비즈니스 에러 코드(예: USER_NOT_FOUND)&lt;/b&gt;를 정의해서 응답해 보세요. 그리고 서버 로그에는 &lt;b&gt;에러 발생 위치(StackTrace)와 당시의 입력값&lt;/b&gt;을 남겨야 합니다. 에러 발생 시각, 사용자의 요청 ID(Trace ID)를 함께 기록하면 수천 개의 로그 사이에서 범인을 찾는 시간이 획기적으로 줄어듭니다.
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;blockquote style=&quot;text-align: center; font-weight: bold; margin-top: 30px; color: #34495e;&quot;&gt;
        &quot;좋은 개발자는 코드가 잘 돌아갈 때가 아니라, 코드가 터졌을 때 진가를 발휘합니다.&quot;
    &lt;/blockquote&gt;
&lt;/div&gt;</description>
      <category>IT 이야기</category>
      <category>exceptionhandling</category>
      <category>nodejs</category>
      <category>Spring</category>
      <category>백엔드</category>
      <category>에러헨들링</category>
      <category>예외처리</category>
      <category>클린코드</category>
      <author>Garam Kim</author>
      <guid isPermaLink="true">https://ramka-devstory.tistory.com/46</guid>
      <comments>https://ramka-devstory.tistory.com/46#entry46comment</comments>
      <pubDate>Fri, 9 Jan 2026 12:00:30 +0900</pubDate>
    </item>
    <item>
      <title>&amp;quot;데이터가 자꾸 꼬여요&amp;quot; 동시성 문제를 해결하는 낙관적 락과 비관적 락</title>
      <link>https://ramka-devstory.tistory.com/44</link>
      <description>&lt;div class=&quot;post-container&quot; style=&quot;font-family: 'Pretendard', -apple-system, sans-serif; line-height: 1.8; color: #333; max-width: 800px; margin: 0 auto;&quot;&gt;
    &lt;p style=&quot;background: #f1f2f6; padding: 15px; border-left: 5px solid #e74c3c; font-style: italic;&quot; data-ke-size=&quot;size16&quot;&gt;
        &quot;재고 1개가 남았는데 2명이 동시에 주문하면 어떻게 될까요?&quot; &lt;br /&gt;
        멀티스레드 환경에서 데이터 정합성을 지키기 위한 필수 전략, &lt;b&gt;낙관적 락(Optimistic Lock)&lt;/b&gt;과 &lt;b&gt;비관적 락(Pessimistic Lock)&lt;/b&gt;을 비교 정리합니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #2c3e50; border-bottom: 2px solid #2c3e50; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;1. 왜 동시성 제어가 필요한가?&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        웹 서버는 여러 사용자의 요청을 동시에 처리합니다. 이때 동일한 데이터(예: 통장 잔고, 티켓 수량)를 동시에 수정하려고 하면, 먼저 처리된 데이터가 무시되거나 비정상적인 값이 저장되는 &lt;b&gt;갱신 손실(Lost Update)&lt;/b&gt; 문제가 발생합니다. 이를 막기 위해 데이터에 '잠금(Lock)'을 걸어야 합니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #e67e22;&quot; data-ke-size=&quot;size26&quot;&gt;2. 비관적 락 (Pessimistic Lock)&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        &quot;데이터 수정 중에 누군가 반드시 접근할 거야&quot;라고 가정하고, 데이터를 읽을 때부터 아예 락을 걸어버리는 방식입니다. DB 수준에서 &lt;code&gt;SELECT ... FOR UPDATE&lt;/code&gt; 구문을 사용하여 구현합니다.
    &lt;/p&gt;
    &lt;ul style=&quot;padding-left: 20px;&quot;&gt;
        &lt;li&gt;&lt;b&gt;장점:&lt;/b&gt; 데이터 정합성을 강력하게 보장하며 충돌을 사전에 차단합니다.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;단점:&lt;/b&gt; 대기 시간이 길어질 수 있어 성능 저하(Deadlock 등)의 위험이 있습니다.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color: #e67e22;&quot; data-ke-size=&quot;size26&quot;&gt;3. 낙관적 락 (Optimistic Lock)&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        &quot;대부분의 경우 충돌이 나지 않을 거야&quot;라고 가정합니다. DB의 락 기능을 쓰지 않고 &lt;b&gt;버전(Version)&lt;/b&gt; 컬럼을 활용해 애플리케이션 수준에서 관리합니다.
    &lt;/p&gt;
    &lt;ul style=&quot;padding-left: 20px;&quot;&gt;
        &lt;li&gt;&lt;b&gt;장점:&lt;/b&gt; 별도의 락을 잡지 않아 성능상 이점이 큽니다.&lt;/li&gt;
        &lt;li&gt;&lt;b&gt;단점:&lt;/b&gt; 충돌이 났을 때 개발자가 직접 롤백 로직을 짜야 하므로 복잡도가 높아질 수 있습니다.&lt;/li&gt;
    &lt;/ul&gt;

    &lt;h2 style=&quot;color: #2c3e50;&quot; data-ke-size=&quot;size26&quot;&gt;  실무 노트&lt;/h2&gt;
    &lt;div style=&quot;background: #f0f7ff; padding: 20px; border-radius: 8px; border-left: 5px solid #3498db;&quot;&gt;
        &lt;p style=&quot;margin-top: 0;&quot; data-ke-size=&quot;size16&quot;&gt;
            어떤 락을 쓸지는 **트래픽의 특성**에 따라 정해야 합니다. 충돌이 빈번하게 일어나는 '인기 공연 티켓 예매' 같은 곳은 비관적 락이 안전하고, 충돌이 거의 없는 '게시글 수정' 같은 곳은 낙관적 락이 효율적이죠.
        &lt;/p&gt;
        &lt;p data-ke-size=&quot;size16&quot;&gt;
            &lt;b&gt;팁:&lt;/b&gt; 만약 여러 대의 서버(분산 서버)에서 공유 자원을 관리해야 한다면, Redis의 &lt;code&gt;Redlock&lt;/code&gt; 같은 &lt;b&gt;분산 락(Distributed Lock)&lt;/b&gt;을 고려해야 합니다. 주니어 시절에는 이 락들이 각각 어디서(DB vs App vs Redis) 관리되는지 구분하는 연습을 해보세요.
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;blockquote style=&quot;text-align: center; font-weight: bold; margin-top: 30px; color: #34495e;&quot;&gt;
        &quot;성능과 데이터 무결성 사이의 줄타기, 그것이 백엔드 개발자의 숙명입니다.&quot;
    &lt;/blockquote&gt;
&lt;/div&gt;</description>
      <category>IT 이야기</category>
      <category>db설계</category>
      <category>transaction</category>
      <category>낙관적락</category>
      <category>데이터베이스</category>
      <category>동시성문제</category>
      <category>백엔드</category>
      <category>비관적락</category>
      <author>Garam Kim</author>
      <guid isPermaLink="true">https://ramka-devstory.tistory.com/44</guid>
      <comments>https://ramka-devstory.tistory.com/44#entry44comment</comments>
      <pubDate>Thu, 8 Jan 2026 12:00:32 +0900</pubDate>
    </item>
    <item>
      <title>&amp;quot;주소창에 엔터를 친 후&amp;quot; 브라우저가 화면을 그리는 5단계</title>
      <link>https://ramka-devstory.tistory.com/45</link>
      <description>&lt;div class=&quot;post-container&quot; style=&quot;font-family: 'Pretendard', -apple-system, sans-serif; line-height: 1.8; color: #333; max-width: 800px; margin: 0 auto;&quot;&gt;
    &lt;p style=&quot;background: #f1f2f6; padding: 15px; border-left: 5px solid #2ecc71; font-style: italic;&quot; data-ke-size=&quot;size16&quot;&gt;
        &quot;내가 짠 코드가 어떻게 실제 화면이 될까요?&quot; &lt;br /&gt;
        성능 좋은 웹사이트를 만들기 위해 반드시 알아야 할 브라우저의 내부 동작 원리, &lt;b&gt;주요 렌더링 경로(Critical Rendering Path)&lt;/b&gt;를 정리합니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #2c3e50; border-bottom: 2px solid #2c3e50; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;1. 렌더링의 5단계 과정&lt;/h2&gt;
    &lt;div style=&quot;background: #fafafa; padding: 15px; border-radius: 8px; border: 1px solid #eee;&quot;&gt;
        &lt;ol style=&quot;margin: 0; padding-left: 20px;&quot;&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;DOM 트리 생성:&lt;/b&gt; 서버로부터 받은 HTML을 파싱하여 객체 모델인 DOM(Document Object Model)을 만듭니다.&lt;/li&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;CSSOM 트리 생성:&lt;/b&gt; 스타일시트(CSS)를 파싱하여 CSSOM(CSS Object Model)을 만듭니다.&lt;/li&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;렌더 트리(Render Tree) 결합:&lt;/b&gt; DOM과 CSSOM을 합쳐 실제로 화면에 보일 요소들만 골라 렌더 트리를 구성합니다.&lt;/li&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;레이아웃(Layout):&lt;/b&gt; 각 노드가 화면의 정확히 어느 위치에, 어떤 크기로 배치될지 계산합니다.&lt;/li&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;페인트(Paint):&lt;/b&gt; 계산된 레이아웃을 바탕으로 화면에 실제 픽셀을 그립니다.&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/div&gt;

    &lt;h2 style=&quot;color: #e67e22;&quot; data-ke-size=&quot;size26&quot;&gt;2. 리플로우(Reflow)와 리페인트(Repaint)&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        자바스크립트로 DOM을 수정하면 브라우저는 다시 레이아웃을 계산하고(Reflow) 화면을 다시 그립니다(Repaint). 이 과정이 빈번하게 일어나면 화면 버벅임의 원인이 됩니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #2c3e50;&quot; data-ke-size=&quot;size26&quot;&gt;  실무 노트&lt;/h2&gt;
    &lt;div style=&quot;background: #fdf2f2; padding: 20px; border-radius: 8px; border-left: 5px solid #e74c3c;&quot;&gt;
        &lt;p style=&quot;margin-top: 0;&quot; data-ke-size=&quot;size16&quot;&gt;
            면접에서 &quot;브라우저 성능을 어떻게 개선했나요?&quot;라는 질문을 받으면 이 렌더링 과정을 활용해 답변해 보세요.
        &lt;/p&gt;
        &lt;p data-ke-size=&quot;size16&quot;&gt;
            &lt;b&gt;팁:&lt;/b&gt; 예를 들어, &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; 태그를 HTML 하단에 두는 이유는 JS 파싱이 DOM 생성을 방해(Block)하지 않게 하기 위해서입니다. 또한 애니메이션을 구현할 때 &lt;code&gt;width&lt;/code&gt;나 &lt;code&gt;top&lt;/code&gt; 대신 &lt;b&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/b&gt;이나 &lt;b&gt;&lt;code&gt;opacity&lt;/code&gt;&lt;/b&gt;를 쓰면 리플로우 과정을 건너뛰고 바로 페인트(정확히는 합성) 단계로 가기 때문에 훨씬 부드러운 화면을 제공할 수 있습니다.
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;blockquote style=&quot;text-align: center; font-weight: bold; margin-top: 30px; color: #2d3436;&quot;&gt;
        &quot;브라우저의 마음을 이해할 때, 비로소 끊김 없는 사용자 경험(UX)이 완성됩니다.&quot;
    &lt;/blockquote&gt;
&lt;/div&gt;</description>
      <category>IT 이야기</category>
      <category>CRP</category>
      <category>CS</category>
      <category>cssom</category>
      <category>dom</category>
      <category>브라우저렌더링</category>
      <category>웹성능최적화</category>
      <author>Garam Kim</author>
      <guid isPermaLink="true">https://ramka-devstory.tistory.com/45</guid>
      <comments>https://ramka-devstory.tistory.com/45#entry45comment</comments>
      <pubDate>Thu, 8 Jan 2026 12:00:29 +0900</pubDate>
    </item>
    <item>
      <title>&amp;quot;유지보수 지옥에서 탈출하기&amp;quot; 객체지향 설계의 5가지 원칙: SOLID</title>
      <link>https://ramka-devstory.tistory.com/42</link>
      <description>&lt;div class=&quot;post-container&quot; style=&quot;font-family: 'Pretendard', -apple-system, sans-serif; line-height: 1.8; color: #333; max-width: 800px; margin: 0 auto;&quot;&gt;
    &lt;p style=&quot;background: #f1f2f6; padding: 15px; border-left: 5px solid #3498db; font-style: italic;&quot; data-ke-size=&quot;size16&quot;&gt;
        &quot;기능 하나 고쳤는데 왜 다른 곳에서 에러가 날까요?&quot; &lt;br /&gt;
        변화에 유연하고 확장이 쉬운 코드를 만드는 5가지 핵심 원칙, &lt;b&gt;SOLID&lt;/b&gt;를 주니어의 시각에서 쉽게 정리했습니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #2c3e50; border-bottom: 2px solid #2c3e50; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;1. SOLID 원칙이란?&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        로버트 마틴이 명명한 객체지향 설계의 5대 원칙입니다. 이 원칙들을 잘 지키면 코드의 가독성이 좋아지고, 변경 사항이 생겼을 때 수정해야 할 범위가 최소화됩니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #e67e22;&quot; data-ke-size=&quot;size26&quot;&gt;2. 5가지 원칙 핵심 요약&lt;/h2&gt;
    &lt;div style=&quot;background: #fafafa; padding: 15px; border-radius: 8px; border: 1px solid #eee;&quot;&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px;&quot;&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;SRP (단일 책임 원칙):&lt;/b&gt; 한 클래스는 하나의 책임만 가져야 합니다. 클래스가 변경되는 이유는 단 하나여야 합니다.&lt;/li&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;OCP (개방-폐쇄 원칙):&lt;/b&gt; 확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 합니다. 기존 코드를 고치지 않고 기능을 추가할 수 있어야 합니다.&lt;/li&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;LSP (리스코프 치환 원칙):&lt;/b&gt; 자식 클래스는 언제나 부모 클래스를 대체할 수 있어야 합니다. 다형성의 규칙을 지키라는 뜻입니다.&lt;/li&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;ISP (인터페이스 분리 원칙):&lt;/b&gt; 자신이 사용하지 않는 메서드에 의존하도록 강제해서는 안 됩니다. 큰 인터페이스보다는 구체적인 여러 개의 인터페이스가 낫습니다.&lt;/li&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;DIP (의존관계 역전 원칙):&lt;/b&gt; 추상화에 의존해야지, 구체화에 의존하면 안 됩니다. 구현 클래스가 아니라 인터페이스를 바라보게 하세요.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;h2 style=&quot;color: #2c3e50;&quot; data-ke-size=&quot;size26&quot;&gt;  실무 노트&lt;/h2&gt;
    &lt;div style=&quot;background: #f0f7ff; padding: 20px; border-radius: 8px; border-left: 5px solid #3498db;&quot;&gt;
        &lt;p style=&quot;margin-top: 0;&quot; data-ke-size=&quot;size16&quot;&gt;
            실무에서 SOLID 원칙을 100% 완벽하게 지키는 것은 매우 어렵습니다. 하지만 &lt;b&gt;OCP&lt;/b&gt;와 &lt;b&gt;DIP&lt;/b&gt;만 제대로 이해하고 적용해도 코드의 질이 완전히 달라집니다.
        &lt;/p&gt;
        &lt;p data-ke-size=&quot;size16&quot;&gt;
            &lt;b&gt;팁:&lt;/b&gt; 새로운 기능을 추가할 때 기존에 잘 돌아가던 &lt;code&gt;if-else&lt;/code&gt; 문을 계속 수정하고 있다면 OCP 위반일 가능성이 높습니다. 이때 인터페이스를 추출하고 다형성을 활용해 보세요. 처음에는 코드가 복잡해지는 것 같아도, 한 달 뒤의 내가 코드를 수정할 때 과거의 나에게 감사하게 될 것입니다.
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;blockquote style=&quot;text-align: center; font-weight: bold; margin-top: 30px; color: #34495e;&quot;&gt;
        &quot;원칙은 도구일 뿐입니다. 상황에 맞게 유연하게 적용하는 감각을 기르세요.&quot;
    &lt;/blockquote&gt;
&lt;/div&gt;</description>
      <category>IT 이야기</category>
      <category>Solid</category>
      <category>객체지향</category>
      <category>디자인패턴</category>
      <category>백엔드</category>
      <category>소프투에어설계</category>
      <category>자바</category>
      <category>클린코드</category>
      <author>Garam Kim</author>
      <guid isPermaLink="true">https://ramka-devstory.tistory.com/42</guid>
      <comments>https://ramka-devstory.tistory.com/42#entry42comment</comments>
      <pubDate>Wed, 7 Jan 2026 12:00:58 +0900</pubDate>
    </item>
    <item>
      <title>&amp;quot;DB 연결이 너무 느리다면?&amp;quot; 커넥션 풀(Connection Pool)의 원리</title>
      <link>https://ramka-devstory.tistory.com/43</link>
      <description>&lt;div class=&quot;post-container&quot; style=&quot;font-family: 'Pretendard', -apple-system, sans-serif; line-height: 1.8; color: #333; max-width: 800px; margin: 0 auto;&quot;&gt;
    &lt;p style=&quot;background: #f1f2f6; padding: 15px; border-left: 5px solid #2ecc71; font-style: italic;&quot; data-ke-size=&quot;size16&quot;&gt;
        &quot;매번 DB를 연결하는 데 걸리는 시간, 아깝지 않으신가요?&quot; &lt;br /&gt;
        서버의 응답 속도를 높이고 안정성을 책임지는 &lt;b&gt;데이터베이스 커넥션 풀(DBCP)&lt;/b&gt;의 내부 동작을 알아봅니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #2c3e50; border-bottom: 2px solid #2c3e50; padding-bottom: 10px;&quot; data-ke-size=&quot;size26&quot;&gt;1. 커넥션 풀이란?&lt;/h2&gt;
    &lt;p data-ke-size=&quot;size16&quot;&gt;
        DB 연결은 비용이 매우 비싼 작업입니다. 매번 TCP 연결을 맺고 끊는 대신, 서버가 실행될 때 미리 일정 수의 연결을 만들어 &lt;b&gt;'풀(Pool)'&lt;/b&gt;에 담아두고, 필요할 때 빌려줬다가 다 쓰면 반납받는 방식을 말합니다.
    &lt;/p&gt;

    &lt;h2 style=&quot;color: #e67e22;&quot; data-ke-size=&quot;size26&quot;&gt;2. 왜 써야 할까? (장점)&lt;/h2&gt;
    &lt;div style=&quot;background: #fafafa; padding: 15px; border-radius: 8px; border: 1px solid #eee;&quot;&gt;
        &lt;ul style=&quot;margin: 0; padding-left: 20px;&quot;&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;응답 속도 향상:&lt;/b&gt; 연결을 맺는 과정이 생략되어 쿼리 실행 시간이 단축됩니다.&lt;/li&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;부하 조절:&lt;/b&gt; 무한정 연결이 생성되는 것을 막아 DB 서버가 과부하로 죽는 것을 방지합니다.&lt;/li&gt;
            &lt;li style=&quot;margin-bottom: 10px;&quot;&gt;&lt;b&gt;자원 재사용:&lt;/b&gt; 이미 생성된 객체를 재사용하여 서버 메모리를 효율적으로 씁니다.&lt;/li&gt;
        &lt;/ul&gt;
    &lt;/div&gt;

    &lt;h2 style=&quot;color: #2c3e50;&quot; data-ke-size=&quot;size26&quot;&gt;  실무 노트&lt;/h2&gt;
    &lt;div style=&quot;background: #fdf2f2; padding: 20px; border-radius: 8px; border-left: 5px solid #e74c3c;&quot;&gt;
        &lt;p style=&quot;margin-top: 0;&quot; data-ke-size=&quot;size16&quot;&gt;
            스프링 부트(Spring Boot)의 기본 커넥션 풀은 &lt;b&gt;HikariCP&lt;/b&gt;입니다. 성능이 매우 뛰어나지만, 설정을 잘못하면 서비스 장애로 이어질 수 있어요.
        &lt;/p&gt;
        &lt;p data-ke-size=&quot;size16&quot;&gt;
            &lt;b&gt;팁:&lt;/b&gt; &lt;code&gt;maximum-pool-size&lt;/code&gt;를 너무 크게 잡으면 DB 서버의 CPU와 메모리가 견디지 못하고, 너무 작게 잡으면 사용자가 대기 줄에서 기다리다 타임아웃이 납니다. 보통은 WAS의 스레드 수와 DB 서버의 사양을 고려해 &lt;b&gt;최적의 수치&lt;/b&gt;를 테스트해 보는 것이 필수입니다. 또한, 쿼리 실행 후 커넥션을 제대로 닫지(반납하지) 않으면 '커넥션 누수'가 발생해 서버가 멈출 수 있으니 주의하세요.
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;blockquote style=&quot;text-align: center; font-weight: bold; margin-top: 30px; color: #2d3436;&quot;&gt;
        &quot;연결은 만드는 것보다 유지하고 관리하는 것이 더 중요합니다.&quot;
    &lt;/blockquote&gt;
&lt;/div&gt;</description>
      <category>IT 이야기</category>
      <category>db</category>
      <category>DBCP</category>
      <category>HikariCP</category>
      <category>Spring</category>
      <category>백엔드</category>
      <category>서버최적화</category>
      <category>커넥션풀</category>
      <author>Garam Kim</author>
      <guid isPermaLink="true">https://ramka-devstory.tistory.com/43</guid>
      <comments>https://ramka-devstory.tistory.com/43#entry43comment</comments>
      <pubDate>Wed, 7 Jan 2026 12:00:42 +0900</pubDate>
    </item>
  </channel>
</rss>