
포트폴리오 소재
-
N+1 문제 해결과 대규모 쿼리 최적화
상황(Situation)
- Django-Silk로 API 성능을 프로파일링한 결과
- 게시글 및 휴지통 목록 조회 시 시리얼라이저(Serializer)의 지연 평가로 인해
- 참조 데이터(시리즈, 태그 등)를 매번 조회하며 최대 21번의 N+1 쿼리가 폭주하는 것을 발견
선택과 이유(Why)
- 파이썬 메모리 단에서 딕셔너리로 캐싱하여 쿼리를 줄이는 방법도 고려
- 하지만 트래픽이 증가하고 한 페이지에 다양한 작성자의 데이터가 노출될 경우
- 애플리케이션 서버의 메모리 부하가 심해질 것이라 판단
- 따라서 데이터의 '조인'과 '집계 연산'에 가장 최적화되어 있는
- 데이터베이스 엔진 자체의 기능을 적극 활용하여 아키텍처를 통일하기로 결정
해결 및 결과(How)
- select_related와 prefetch_related를 적용해 정방향/역방향 참조 데이터를
- 작성자 총 게시글 수 및 좋아요 여부를 구하는 로직은
- Subquery와 Exists를 도입해 메인 쿼리 실행 시 단 한 번의 연산으로 처리하도록 이관
- 결과적으로 API 당 쿼리 발생 횟수를 81%(21개 → 4개) 감소시키고 응답 속도를 45%(31ms → 17ms) 단축
-
동시성 제어 및 데이터 무결성 보장
상황(Situation)
- 사용자가 '좋아요' 버튼이나 '새 시리즈 생성' 버튼을 짧은 순간에 여러 번 클릭할 경우
- 중복 데이터가 생성되는 동시성 이슈(Race Condition)가 발생할 위험이 존재
선택과 이유(Why)
- 애플리케이션 단(Python)에서 if exists()로 먼저 존재 여부를 검사하는 것은
- DB 락(Lock)을 거는 방식은 성능 저하 및 데드락의 위험이 있어
- 가장 오버헤드가 적고 확실한 DB 스키마 레벨의 제약조건(Constraint)을 활용하기로 결정
해결 및 결과(How)
- DB 모델에 복합 고유 제약조건(UniqueConstraint)을 적용하여 중복 데이터 생성을 원천 차단
- 무작정 생성(create())을 시도한 뒤
- 제약 조건 위반으로 발생하는 IntegrityError를 애플리케이션 서비스 계층에서
- 안전하게 예외 처리(Catch)하는 EAFP(허락보다 용서를 구하는 것이 쉽다) 패턴을 적용
- 이를 통해 동시성 이슈가 발생해도 서버 다운 없이 사용자에게 정상적인 400번대 응답을 반환
-
프레임워크 의존도를 낮춘 객체지향적 View 설계 (Mixin)
상황(Situation)
- 게시글 목록 조회, 내 글 조회, 임시글 조회 등 다양한 View 클래스에서
- 쿼리 파라미터 파싱 및 페이지네이션 처리를 위한 코드가 중복해서 발생
선택과 이유(Why)
- DRF가 제공하는 내장 GenericAPIView나 django-filter 라이브러리를 사용하면
- 하지만 프레임워크에 의존하기보다
- 프로젝트의 요구사항에 딱 맞는 공통 로직을 직접 객체지향적으로 추상화해보고 싶었음
- 이를 통해 향후 커스텀 로직 추가 시의 유연성을 확보하고자 했음
해결 및 결과(How)
- 중복되는 로직을 분리하여 커스텀 PostListMixin 클래스를 직접 설계하고,
- 비즈니스 로직은 Service Layer로 철저히 위임하여
- View 계층은 오직 'HTTP 요청 검증과 응답'이라는 단일 책임 원칙(SRP)만 수행하도록
- 가독성과 유지보수성을 극대화
-
한정된 리소스 환경에서의 인프라/외부 연동 안정화
상황(Situation)
- 초기 배포 환경인 AWS EC2(t3.small)에서 제한된 메모리(2GB)로 인해
- 도커 컨테이너 빌드 및 실행 중 OOM(Out of Memory) 현상이 발생
- 또한 외부 소셜 로그인이나 AI API 서버 장애 시 사내 서버까지 마비될 위험이 존재
선택과 이유(Why)
- 서버 사양을 올려(Scale-up) 문제를 쉽게 해결할 수 있지만
- 운영 초기 단계에서 고정 비용을 낭비하지 않고 한정된 인프라 자원의 한계를
- 소프트웨어적으로 극복해 보는 것이 백엔드 개발자로서 더 가치 있는 경험이라고 판단했음
해결 및 결과(How)
- EC2 디스크 공간을 활용해 2GB의 Swap Memory를 할당하여 메모리 부족 현상을 성공적으로 방어
- 외부 API 통신 시 반드시 명시적인 Timeout을 설정하고
- raise_for_status()로 상태 코드를 검증하여
- 외부 서버 장애가 우리 서버의 스레드 무한 대기(Hang) 현상으로 전파되는 것을 차단하는 방어 로직 구축
디자인 수정
홈페이지

프로젝트 페이지

새로운 페이지 추가
