<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>가인쓰 sw개발</title>
    <link>https://chlrkdls1269.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 11 Jun 2026 23:45:54 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>가인</managingEditor>
    <image>
      <title>가인쓰 sw개발</title>
      <url>https://tistory1.daumcdn.net/tistory/6572399/attach/f237a9d9a78548158ae57dc506523562</url>
      <link>https://chlrkdls1269.tistory.com</link>
    </image>
    <item>
      <title>다중 데이터 DB I/O 로직 성능 향상</title>
      <link>https://chlrkdls1269.tistory.com/3</link>
      <description>&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;다중 데이터 DB Input / Output 로직 성능 향상&lt;/h4&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;최근에 새로운 기능을 추가해야하는 일이 있었는데, 요청사항은 이러하다.&lt;br&gt;&amp;nbsp;&lt;br&gt;- AS-IS : 현 시점 기준으로 하나의 사이트 오브젝트 목록을 받아온 후 보여준다.&lt;br&gt;- TO-BE : 사용자가 원하는 시점 기준으로 여러 사이트의 오브젝트 목록을 한 번에 받아와서 보여줘야 함.&lt;br&gt;&amp;nbsp;&lt;br&gt;Gap 차이로는&lt;br&gt;1. 사용자가 원하는 시점 기준으로 오브젝트를 볼 수 있음.&lt;br&gt;2. 하나 이상의 사이트를 모두 한눈에 볼 수 있음.&lt;br&gt;&amp;nbsp;&lt;br&gt;원하는 시점을 불러오는 기능 부분은 오브젝트 History 관련 내용이오니, 해당 글에서는 여러 사이트 목록을 한 번에 가져오는 로직의 성능 향상 부분에 대해서 다룹니다.&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;원래 하나의 사이트 오브젝트를 가져오는 로직은 단순하게 이루어진다.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;Python&quot; data-ke-language=&quot;Python&quot;&gt;&lt;code&gt;def get_object_list(site: str): -&amp;gt; dict
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Q = f'''select * from fn_object_search(site)'''

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result = DB.Query(Q, ...args)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return result
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except Exception as e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;	raise ObjectFindException(str(e))&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;다중으로 사이트의 오브젝트를 가져와야 하니 당연히 반복문을 사용하여 결과 값들을 합쳐서 한번에 return하면 되겠지 해서 다음과 같이 코드를 작성했었다.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;Python&quot; data-ke-language=&quot;Python&quot;&gt;&lt;code&gt;import asyncio

def __get_site_object_list(site: str) -&amp;gt; dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Q = f'''select * from fn_object_search($1)'''
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result = DB.query(Q, site)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return result
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except Exception as e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise ObjectFindException(str(e))


async def get_multiple_site_object_list(sites: list[str]) -&amp;gt; list[dict]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tasks = [__get_site_object_list(site) for site in sites]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;results = await asyncio.gather(*tasks, return_exceptions=False)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return results&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;결론적으로, 위의 코드를 통해 오브젝트를 가져오면 다음과 같은 성능을 나타냈다.&amp;nbsp;&lt;br&gt;- 1개의 사이트 불러오기 : 평균 2.6초&lt;br&gt;- 8개의 사이트 불러오기 : 평균 23초&lt;br&gt;&amp;nbsp;&lt;br&gt;&lt;u&gt;여기서 async를 사용한 비동기처리 함수는 코루틴으로 작동한다.&lt;/u&gt;&lt;br&gt;&amp;nbsp;&lt;br&gt;위의 코드로 빌드하여 개발 서버에 배포 후 이제 실제로 사용할 사이트의 담당자분에게 기능 테스트를 요청하였다.&lt;br&gt;테스트 결과로는 기능은 잘 동작하나, 로딩이 오래걸린다는 답변을 받게되었다.&lt;br&gt;&amp;nbsp;&lt;br&gt;분명 코루틴을 써서 가져왔는데 왜 느려지지...? 라는 생각을 처음으로 갖게 되었다.&lt;br&gt;&amp;nbsp;&lt;br&gt;사실 병렬 처리에 대해 멀티쓰레드가 많이 쓰인다 정도만 알고있지 보통 대부분이 코루틴에 대해서 깊게 생각하고 있진 않다.&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;일단 결론적으로 느려진 원인에 대해서 말하자면&lt;br&gt;내가 사용하던 Python DB Connection 라이브러리인 psycopg2는 동기 Blocking DB I/O 방식이기 때문에&lt;br&gt;비동기 코드에서 호출되더라도 DB 응답을 기다리는 동안 이벤트 루프가 멈추게 되고, 결국 순차적으로 실행되어 성능이 저하되었다.&lt;br&gt;&amp;nbsp;&lt;br&gt;위의 사유로, psycopg2 라이브러리에서는 코루틴 내부에서 Blocking 호출이 발생하여도&lt;br&gt;해당&amp;nbsp;Task가&amp;nbsp;실행되는&amp;nbsp;동안&amp;nbsp;이벤트&amp;nbsp;루프의&amp;nbsp;다른&amp;nbsp;Task가&amp;nbsp;스케줄링되지&amp;nbsp;못하고&amp;nbsp;대기한다.&lt;br&gt;동시성(concurrency)를 보장받지 못해요.....&lt;br&gt;&amp;nbsp;&lt;br&gt;아마 요즘 DB Connection 라이브러리들은 이러한 DB Blocking I/O를 병렬 처리하도록 지원하는 것으로 알고 있다.&lt;br&gt;확인해보니, psycopg3부터는 해당 기능이 개선되었다. 최신 라이브러리 최고...&lt;br&gt;&amp;nbsp;&lt;br&gt;라이브러리를 업데이트 하는 순간 실사용중인 서비스에 리스크가 너무 크고, 책임지고 바꿔야할 부분들이 많아지기 때문에 일단 나는 &lt;span style=&quot;color: #000000;&quot;&gt;라이브러리 업그레이드는 보류한 채&lt;/span&gt;&amp;nbsp;개발 하였다.&lt;/p&gt;&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 멀티 쓰레드를 활용하여 여러 사이트를 가져오도록 로직을 수정하면 성능이 개선되지 않을까?&lt;br&gt;라는 방안을 고안하여 바로 로직에 적용해보았다.&lt;/p&gt;&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;Python&quot; data-ke-language=&quot;Python&quot;&gt;&lt;code&gt;import asyncio
from concurrent.futures import ThreadPoolExecutor
from typing import List, Dict

# workers 수는 환경에 따라 맞게 설정해야 해요..!
executor = ThreadPoolExecutor(max_workers=10)

def __get_site_object_list(site: str) -&amp;gt; Dict:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Q = &quot;SELECT * FROM fn_object_search($1)&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result = DB.query(Q, site)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return result
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;except Exception as e:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raise ObjectFindException(str(e))


async def get_multiple_site_object_list(sites: List[str]) -&amp;gt; List[Dict]:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;loop = asyncio.get_running_loop()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tasks = [loop.run_in_executor(executor, __get_site_object_list, site) for site in sites]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;results = await asyncio.gather(*tasks, return_exceptions=False)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return results&lt;/code&gt;&lt;/pre&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;br&gt;이렇게 하면 백엔드 서버와 DB간 Data I/O Task에 멀티 쓰레드 로직을 적용할 수 있다.&lt;br&gt;&amp;nbsp;&lt;br&gt;결과는 ....!&lt;br&gt;- 1개의 사이트 불러오기 : 평균 2.6초 -&amp;gt; 작업 x&lt;br&gt;- 8개의 사이트 불러오기 : 평균 23초 -&amp;gt; 코루틴 적용&lt;br&gt;- 8개의 사이트 불러오기 : 평균 3.3초 -&amp;gt; 멀티 스레드 적용&lt;br&gt;&amp;nbsp;&lt;br&gt;N번의 Task 진행을 동시 Task 작업으로 변경하여 실제로 서비스 API 속도를 대폭 개선하였고&lt;br&gt;해당 담당자의 테스트 결과도 OK 되었다.&lt;/p&gt;</description>
      <category>백엔드/FastAPI</category>
      <category>Data I/O</category>
      <category>FastAPI</category>
      <category>멀티 스레드</category>
      <category>비동기 처리</category>
      <category>코루틴</category>
      <category>파이썬</category>
      <author>가인</author>
      <guid isPermaLink="true">https://chlrkdls1269.tistory.com/3</guid>
      <comments>https://chlrkdls1269.tistory.com/3#entry3comment</comments>
      <pubDate>Sat, 15 Nov 2025 15:54:29 +0900</pubDate>
    </item>
    <item>
      <title>서버 DB 커넥션 풀 관리</title>
      <link>https://chlrkdls1269.tistory.com/2</link>
      <description>&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;서버에서 DB 커넥션 풀 설정 정리&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 웹 서비스 및 별도 서비스 제공 목적으로 총 세개의 백엔드 프레임워크를 사용하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- FastAPI&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Spring Boot&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Node.js Express&lt;/p&gt;
&lt;p data-ke-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;- Fiddler Classic 트래픽 캡쳐를 통한 Injection 시도 및 패킷 Parameter 변조&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Http Watch를 사용하여 API 호출에 몇초의 시간이 걸리는지 점검&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클러스터 내 백엔드 서버 파드에 연결되어있는 PVC를 통한 로그 모니터링&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클러스터 내 백엔드 서버 CPU 및 메모리 리소스 모니터링&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순한 데이터 인터페이스하는 API 개발일지 언정 해외에서도 이용하는 대규모 서비스다 보니 신경써야 할 부분이 많이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;※ &lt;/span&gt;서비스 지연이나 서비스 중단은 운영팀에게 치명적이다..&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에 DB 서버에 Max Pool Connection 관련하여 과부하가 걸려 서비스 제공에 문제가 되는 일이 발생하였다.&lt;/p&gt;
&lt;p data-ke-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;text-align: start;&quot;&gt;Node.js Express DB 설정쪽에 Connection Pool이 너무 과도하게 많이 잡혀있었어서&amp;nbsp;발생하였고&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 여러 문서들을 보면서 Connection Pool을 최적화를 진행하였었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러 문서들을 찾아보았을 때 거의 공식이다 싶이 다들 추천하는 Connection Pool이 있었는데,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;pool_connection = ((cpu_core_count * 2) + effiective_spindle_count)&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;당시 개발 서버의 CPU 코어수는 6개 였기 때문에 6 * 2 + 1 해서 13인데 그래도 여유롭게 20으로 설정했었다.&lt;/p&gt;
&lt;p data-ke-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;size14&quot;&gt;&lt;span style=&quot;color: #ef5369;&quot;&gt;※ 운영 서버까지 안가고 개발 서버에서 중단된 것이 참 다행이라고 생각한다. 개발 서버도 많은 임직원분들이 테스트하는데 사용하시기에 해당 문제를 운영서버 반영 전 미리 찾을 수 있었다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 반대로 백엔드 개발 서버가 oom(Out Of Memory)가 발생하여 서비스가 중단되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음 연락을 받았을때, Nginx에 설정되어있는 데이터 I/O Body Size에 의해 서비스 중단된 것으로 추측된다고 연락을 받았었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 확인 결과, 서비스 중단되어 내려갔던 파드의 PV에 적재되어있는 마지막 로그를 확인해보니 &lt;span style=&quot;text-align: start;&quot;&gt;실제 발생 원인은 &lt;/span&gt;Out Of Memory가 원인이였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Connection Pool을 줄이게 되면 동시에 DB I/O를 처리할 수 있는 수가 줄어들고, 나머지 큐들은 Memory에 대기큐로 존재한다는 것인데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 또한 대기큐에 걸려 순차적으로 처리할 수 있도록 의도적으로 설계하여 Connection Pool을 최적화한 것이였는데&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대기큐에 걸려있는 데이터의 양이 아무래도 국내 및 해외 모든 공장의 시스템 데이터를 관리하는 데이터이고 사이즈가 다들 크기 때문에 메모리를 많이 사용하여 결론적으로 Out Of Memory를 발생시켰다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이 상황에서 Connection Pool을 최적화한 공식으로 냅두고 서버 메모리를 증설하는 것도 정답일 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 클러스터의 리소스를 생각하지 않고 맘대로 무한정으로 서버 메모리를 증설시킬 수 없고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 그렇다고 &lt;span style=&quot;text-align: start;&quot;&gt;Connection Pool을 최적화 한 후 타임 아웃 시간을 늘려서&amp;nbsp;&lt;/span&gt;대기큐에 두어 서비스를 느리게 제공할 수 없기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리를 운영서버와 동일하게 개발서버 또한 2Gi에서 6Gi로 늘리고 Connection Pool을 조금 더 여유롭게 두기로 결정하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식은 다음과 같이 적용하였다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;connection_pool = ((cpu_core_count * 2) + current_user_count + effective_spindle_count)&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;단순 Small size 데이터 I/O라면 커넥션 풀 최적화한 공식이 맞겠지만, I/O하는 데이터 사이즈가 매우 크다보니&lt;/p&gt;
&lt;p data-ke-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;DB 커넥션 풀에 대해서 진지하게 고려해본적이 없었고, 매번 그저 여유있게 설정해두기 마련이었는데&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근 이와 관련하여 여러 이슈가 발생했다 보니 개발할 때 사소한 것이라도 신경써서 진행해야 한다는 생각이 종종 들게 되는 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DB, SQL/Connection Pool</category>
      <category>Connection pool</category>
      <category>DB</category>
      <category>PostgreSQL</category>
      <category>서버</category>
      <author>가인</author>
      <guid isPermaLink="true">https://chlrkdls1269.tistory.com/2</guid>
      <comments>https://chlrkdls1269.tistory.com/2#entry2comment</comments>
      <pubDate>Sat, 15 Nov 2025 13:18:23 +0900</pubDate>
    </item>
  </channel>
</rss>