반응형

전체 글 178

ElastiCache Redis Read/Write Splitting 적용기 - 장애에서 배운 이중화 전략

실제 프로덕션 Redis 장애를 겪고, 읽기/쓰기 분리를 적용하면서 배운 것들을 정리합니다.배경: Redis 장애가 터졌다어느 날 프로덕션 서비스가 전체적으로 느려졌다. API 응답 시간이 수십 배로 치솟고, Sentry에는 Redis timeout 에러가 쏟아졌다. 원인은 AWS ElastiCache t-type 인스턴스의 CPU Credit 소진이었다.t-type 인스턴스는 CPU Credit 기반으로 동작한다. 평소에는 Credit을 적립하고, 트래픽이 몰리면 Credit을 소모하면서 버스트 성능을 제공한다. 그런데 이날은 트래픽 급증으로 Credit이 바닥나버렸고, CPU 성능이 baseline(5~40%)으로 제한되면서 Redis가 극도로 느려진 것이다.Automatic Failover는 왜 동..

ElastiCache Redis 읽기/쓰기 분리 (Primary / Replica)

배경운영 중인 Django 백엔드의 Redis 캐시가 ElastiCache 클러스터(Primary 1 + Replica 2)로 구성되어 있었지만, 설정이 Primary Endpoint 하나만 가리키고 있어서 모든 읽기/쓰기 트래픽이 Primary 노드에 집중되고 있었다. ElastiCache가 제공하는 Reader Endpoint를 활용해 읽기는 Replica로, 쓰기는 Primary로 분산하는 작업을 했다.1. ElastiCache 엔드포인트 종류ElastiCache Redis 클러스터를 생성하면 세 종류의 엔드포인트가 제공된다.엔드포인트연결 대상용도Primary EndpointPrimary 노드 고정읽기 + 쓰기Reader Endpoint (-ro)Replica 노드들 (라운드로빈)읽기 전용개별 노드..

Django DRF에서 N+1 쿼리를 잡은 날 — Datadog에서 Prefetch까지

TLI (Today I Learned) · 2026-02-20태그: django drf orm n+1 prefetch datadog오늘의 작업/api/v2/stadium-groups/{id}/ API에서 Datadog APM을 통해 N+1 쿼리를 발견했고,Prefetch로 해결했다. 브랜치 생성 → 코드 수정 → 테스트 작성 → PR까지 한 사이클을 돌았다.문제 발견 — Datadog APM최근 배포 직후 Datadog에서 특정 API 트레이스를 확인했다.trace_id: 1981294581012217384span: stadium_image 쿼리 × 14회14개의 stadium_image SELECT가 개별로 날아가고 있었다.로직을 보면 즉시 이해가 됐다.AS-IS 코드 — 왜 N+1이 생겼나# Stad..

AWS Lambda 환경에서 S3 Presigned URL이 만료되는 문제 해결기

문제 발견어드민 페이지에서 매니저가 제출한 증빙서류 이미지가 엑박으로 표시되는 버그가 보고되었다. 일부 이미지는 정상적으로 보이는데, 특정 이미지들만 엑박이 뜨는 상황이었다.엑박이 뜨는 이미지의 URL로 직접 접속해보니 S3에서 다음과 같은 에러를 반환하고 있었다. ExpiredToken The provided token has expired.시스템 구조프로젝트는 Django 기반 REST API 서버로, AWS Lambda + API Gateway 환경에서 운영되고 있다. 이미지 파일은 S3에 저장되며, 조회 시 Presigned URL을 생성하여 응답한다.[클라이언트] → [API Gateway] → [Lambda (Django)] → [S3 Presigned URL 생성] ..

Obsidian Claudian 플러그인 설치 및 트러블슈팅 가이드

요즘 나의 제 2의 뇌를 만들기 위해 하루 일과나 있었던 일들 그리고 나의 감정들을 옵시디언에 기록하고 있다. 너무 재밌음.나중에는 이 기록들을 내가 자연어로 물어보기만 하면 답변을 바로 받을 수 있게끔 하기 위해서 클로디안 이라는 플러그인을 찾아냈다.이게 뭐냐면..바로 그냥 옵시디언 앱에서 클로드를 활용할 수 있다는 플러그인이었다.이번 포스팅에서는 내가 직접 Obsidian에서 Claude Code를 사이드바 채팅으로 사용할 수 있는 Claudian 플러그인을 설치하면서 겪은 문제들과 해결 과정을 정리했다.환경macOS (Apple Silicon)Obsidian 최신 안정 버전Claude Code 2.1.39 (Native Binary)Claudian 1.3.63Claudian이란?Claudian은 C..

Claude Code에서 MySQL MCP 서버 SSL 연결 문제 해결하기

Claude Code를 사용하다 보면 MCP(Model Context Protocol) 서버를 통해 다양한 외부 서비스와 연동할 수 있다. 그중에서도 MySQL 데이터베이스 연결은 개발 작업에 꽤 유용한데, 최근 AWS RDS MySQL에 연결하려다 꽤나 고생했던 경험을 공유하려고 한다.문제 상황어느 날 claude mcp list 명령어를 실행했더니 MySQL MCP 서버만 연결에 실패하고 있었다.$ claude mcp listcontext7: https://mcp.context7.com/mcp (HTTP) - ✓ Connectedsequential-thinking: npx @modelcontextprotocol/server-sequential-thinking - ✓ Connectedmysql: npx..

Django ORM aggregate Sum이 NULL을 반환할 때

오늘 코드 리뷰 받다가 알게 된 내용 정리.발단프라임타임 점수 계산 로직에서 이렇게 썼었다:def calculate_score_for_stadium(self, stadium_id: int) -> int: result = ( FixedMatch.objects.prime_time_weekday() .for_stadium(stadium_id) .aggregate(total_score=Sum(self._build_score_case_expression())) ) return result["total_score"] or 0 # _build_score_case_expression()에서 이미 default=Value(0)을 설정했는데, or 0이 필요한지 의문..

Django ORM __in 조회에 딕셔너리 전달하면 어떻게 될까?

오늘 코드 리뷰 받다가 알게 된 내용 정리.발단프라임타임 점수 계산 로직을 짜면서 이렇게 썼었다:SCORE_BY_HOUR = { 19: 1, 20: 2, 21: 1,}# 이렇게 썼음FixedMatch.objects.filter( match_time__hour__in=list(self.SCORE_BY_HOUR.keys()), # [19, 20, 21])그런데 리뷰에서 list() 변환이 불필요하다는 피드백을 받았다.# 이렇게 해도 된다고?FixedMatch.objects.filter( match_time__hour__in=self.SCORE_BY_HOUR, # dict 자체를 전달)왜 동작하는가?Python 딕셔너리의 기본 동작Python에서 딕셔너리를 iterate하면 기본..

2025 뉴발 run your way 대회 후기

작년 처음으로 시작한 10km 대회를 올해에도 운이 좋게 참여할 수 있었다대회 약 일주일 전, 패키지가 도착했고 역시 메이저 대회 답게 패키지 구성이 너무 알찼다패키지 구성은 제대로 사진찍어놓지 않아서 없음 ,,,아무튼 대회 당일날이 되었고, 이게 웬일.. 대회날에 비가오는 거다..우중 대회는 첨이라서 걱정이 많았지만 일단 가~,,~ 어떻게든 되겠지~~대회장에는 역시 많은 사람들이 있었다.대회 장소는 여의도공원!도착해서 잠시 비를 피하면서 편의점에서 우비를 하나 사서 우비를 입고 대회 시작하면 벗을 생각이었다.우비를 진짜 오랜만에 입어본듯 체온 유지에 짱~ 나는 출발 그룹이 B 그룹이었고 꽤나 앞쪽에서 출발했었다.B 그룹의 45분 페이스 메이커와 같이 출발하려고 했는데 그건 실패했다... 그래서 초반에 ..

혼자여도 맛있고, 간단하게 - 밥풀

약 한달 간의 여정으로 배포에 성공한 밥풀 ios 앱을 출시하게 되었다.!데이트 코스 추천 웹 서비스를 개발하다가 러닝 날씨 정보 관련 앱을 만들어 보다가 결국 돌고 돌아서 요리를 자주하게 되면서 만들게 된 나의 첫 번째 앱flutter로 언젠가는 만들어보겠다는 다짐을 성공..~아직 많이 부족하지만 이렇게나 많이 붙여보고 싶은게 있으니 차근차근 해봐야겠다~밥풀 앱 다운로드

반응형