본문 바로가기

전체 글

(39)
[Redis] 복잡한 락 없이 Redis의 INCR로 동시성 이슈 해결하기 1. 개요이전 포스트에서 말씀드린 것처럼, 그라밋 서비스에는 사용자가 실험 공고를 작성할 때, 부가 정보를 자동 완성해주는 기능이 있습니다. 이 기능은 한 사용자가 하루에 두 번까지만 사용할 수 있도록 서버에서 제어하고 있습니다. 기존에는 로그 테이블에 쌓인 데이터 행 수를 기준으로 사용 횟수를 제한했는데, 생각해보니 동시성 문제 가능성이 충분히 있더라고요...? 🤔 2. 문제 상황해당 기능의 사용 횟수를 제한하는 로직은 다음과 같았습니다.사용자가 요청-> ExperimentPostKeywordsLog 테이블에서 member_id와 created_at을 기준으로 로그 개수를 조회-> 데이터 개수가 2개를 넘지 않은 경우에만 키워드 추출 로직을 진행 만약에 사용자가 빠르게 연속해서 요청을 보낸다면,..
[DB] 커버링 인덱스로 풀 테이블 스캔 줄이기 1. 개요보상이 주어지는 실험 공고를 쉽게 확인할 수 있는 플랫폼, ‘그라밋’ 프로젝트에서 실험 공고를 작성할 때 실험 장소, 실험 대상, 보상 등 다양한 부가 정보를 수기로 입력해야 했습니다. 공고의 본문만 읽더라도 사용자(대학생)들이 본인에게 적합한 실험인지 쉽게 판단할 수 있도록 UI를 설계했기 때문입니다. 다만, 실험 공고를 업로드하는 대학원생들 입장에서는 다소 번거로운 작업이 될 수 있죠...이 문제를 해결하기 위해, 이번에 공고 본문을 올리면 AI가 실험 장소, 실험 대상, 보상 등의 키워드를 자동으로 추출해주는 기능을 도입했습니다. 하지만 서드파티 API를 사용하다 보니 비용 문제를 고려해 하루에 사용자당 2회로 사용 횟수를 제한하기로 했습니다. 2. 문제 상황실험 공고 키워드 추출 API..
[DB] 복합 인덱스로 불필요한 Filesort를 제거하기 1. 개요‘그라밋’ 프로젝트에는 사용자들에게 다양한 실험 공고를 필터링 조건에 맞춰 보여주는 기능을 제공합니다. 그 중 recruit_status = true 조건을 가진 게시글만 created_at 기준으로 정렬해 조회하는 쿼리가 있었는데, 정렬 과정에서 filesort가 발생하면서 성능 저하 우려가 있었습니다. 특히 공고 데이터가 많아질수록 ORDER BY created_at 구문이 매번 정렬 연산을 수행해야 하므로, 쿼리 효율이 점점 떨어질 수 있었습니다. 2. Filesort란?MySQL에서 ORDER BY는 크게 인덱스를 이용한 정렬과 filesort 방식으로 나눌 수 있습니다. 인덱스 정렬: 인덱스가 이미 정렬된 순서를 유지하고 있어 해당 순서대로 데이터를 읽기만 하면 되므로 매우 빠릅니다..
[MSA] 모놀리스에서 MSA까지: 핵심 개념과 기술 정리 1. 들어가며최근 많은 기업들이 Monolithic Architecture(모놀리스 아키텍처)에서 Microservices Architecture(마이크로서비스 아키텍처, MSA)로 전환하고 있습니다. 모놀리스는 하나의 코드베이스와 실행 환경에서 서비스가 동작하기 때문에 관리가 비교적 간단하지만, 확장성, 배포 유연성과 서비스 독립성 측면에서 한계가 있습니다. 이번 글에서는 모놀리스에서 MSA로 전환할 때 마주치는 문제들과 이를 해결하기 위해 등장한 핵심 기술을 정리해 보겠습니다. 2. Monolithic Architecture란? 모놀리스는 하나의 코드베이스가 하나의 실행 환경에서 동작하는 아키텍처입니다.배포 단위가 하나이기 때문에 특정 기능만 확장하고 싶어도 전체 애플리케이션을 스케일링해야 합니다. ..
[Spring] SpringBoot에서 AOP와 MDC를 활용한 로깅 시스템 구축하기 (feat. 민감 정보 마스킹) 1. 개요YAPP에서 진행 중인 ‘그라밋’ 프로젝트에서는 개발 및 운영 환경에서 발생하는 로그를 AWS CloudWatch에 기록하고 있습니다. 지금까지는 스케줄링 작업이나 예외 로그만 수집해왔지만, 서비스 고도화 과정에서 요청과 응답도 로깅할 필요성이 커졌습니다. @RestController@RequestMapping("/api")class ExampleController { private val log: Logger = LoggerFactory.getLogger(this::class.java) @GetMapping("/example") fun getExample(@RequestParam name: String): ResponseEntity { log.info("[Reque..
[Architecture] 그라밋 프로젝트, 클린 아키텍처 입히기 1. 개요YAPP에서 진행 중인 ‘그라밋’ 프로젝트에 클린 아키텍처를 도입하기로 결정했습니다. 이전 프로젝트 ‘삐삐’에서는 멀티 모듈 구조를 적용해 도메인 간의 의존성을 분리하면서, 특정 도메인의 변경이 다른 도메인에 영향을 주지 않도록 설계했습니다. 덕분에 유지보수성이 크게 향상되는 걸 경험했습니다.하지만 프로젝트가 커지고 기능이 추가될수록, 서비스 계층이 점점 비대해지는 문제를 겪었습니다. 모듈을 나누긴 했지만, 여전히 외부 의존성(ex. DB, Framework 등)에 깊게 묶여 있다는 점도 고민이었습니다. 이런 문제를 해결할 방법을 찾던 중, 비즈니스 로직이 특정 계층에 몰리지 않으면서도 외부 변경에 유연하게 대응할 수 있는 구조인 클린 아키텍처를 알게 되었습니다.   2. 클린 아키텍처1) 클린..
[AWS] 이미지 WebP 변환 Lambda 실행 속도 개선 일지 1. 개요최근 진행하는 그라밋 프로젝트에서 이미지 로딩 시간을 개선하기 위해 AWS Lambda를 통해 이미지를 WebP로 변환하는 작업을 했습니다.  S3 버킷에 올라가는 이미지라면 자동으로 WebP 변환이 되어 이미지 용량을 크게 개선해주어 문제가 없는 줄 알았으나... 프론트에서 WebP 변환된 이미지를 바로 불러오지 못하는 이슈가 있었습니다. 저희 서비스에서 실험자 역할의 회원이 실험 공고를 등록할 때, 이미지도 같이 업로드할 수 있는데 실험 공고 등록 완료 후, 회원이 등록한 실험 공고 상세 페이지로 바로 이동합니다. 이때, 원본 이미지를 업로드하고 이미지 변환 과정을 거치는데 변환 과정에서 시간이 걸려 회원이 공고를 등록하자마자 이동하는 공고 상세 페이지에서 이미지를 제대로 보여주지 못하는 문..
[RealMySQL 8.0] 8. 인덱스 - 기타 인덱스 (멀티 밸류 인덱스, 클러스터링 인덱스, 유니크 인덱스, 외래키) 8.7 멀티 밸류 인덱스전문 검색 인덱스를 제외한 모든 인덱스는 레코드 1건이 1개의 인덱스 키 값을 가진다. 즉, 인덱스 키와 데이터 레코드는 1:1의 관계를 가진다. 하지만 멀티 밸류 인덱스는 하나의 데이터 레코드가 여러 개의 키 값을 가질 수 있는 형태의 인덱스다. 최근 RDBMS들이 JSON 데이터 타입을 지원하기 시작하면서 JSON의 배열 타입의 필드에 저장된 원소들에 대한 인덱스 요건이 발생한 것이다.  다음과 같이 신용 정보 점수를 JSON 타입 칼럼에 저장하는 테이블을 가정해보자.mysql> CREATE TABLE user ( user_id BIGINT AUTO_INCREMENT PRIMARY KEY, first_name VARCHAR(10), last_name ..