테스트가 지옥이 되는 첫 순간은, 의외로 실행이 느려질 때가 아니다. Given을 다섯 번째 쓸 때다.게시글 댓글 테스트 하나를 추가하는데, 댓글을 쓰려면 게시글이 있어야 하고, 게시글이 있으려면 작성자가 있어야 하고, 작성자는 OAuth provider가 있어야 하고… 이 체인이 테스트 본문을 50줄 잠식한다. 그리고 다음 테스트도, 그 다음 테스트도 똑같다.@Testfun `댓글이 정상 추가된다`() { val author = User( email = "test@example.com", nickname = "tester", password = "encoded", role = Role.USER, provider = AuthProvide..
“Redis 붙이기 전에, 애플리케이션 안에서 할 수 있는 캐싱부터 제대로 써보자.”이 글을 쓰게 된 계기캐시라고 하면 자연스럽게 Redis부터 떠올렸다.나도 처음에는 “캐시 = Redis, 네트워크 뒤에 있는 뭔가 빠른 저장소” 정도로만 생각했다.근데 실제로 API를 최적화해 보니,모든 캐시를 굳이 네트워크 너머에 둘 필요는 없다는 걸 느꼈다.“JVM 안에서만 써도 되는 값”“인스턴스별로 달라도 괜찮은 값”“조금 부정확해도 괜찮은, 읽기 위주의 값”이런 것들은 오히려 로컬 캐시(Local Cache)가 더 잘 맞는 경우가 많았다.그 와중에 Spring에서 가장 손쉽게 쓸 수 있는 라이브러리 중 하나가 바로 Caffeine이다.이 글은,Caffeine이 어떤 특징을 가진 로컬 캐시인지Spring Cach..
“Kafka를 쓰기엔 무겁고, 그냥 동기 호출만 하기엔 아쉬울 때.”이 글을 쓰게 된 계기마이크로서비스까지는 아니더라도,서비스 레이어가 조금씩 나뉘기 시작하면 자연스럽게 “이벤트” 이야기가 나온다.주문이 생성되면 알림 서비스를 호출해야 하고유저가 가입하면 추천/포인트/메일링 시스템이 반응해야 한다.처음에는 대부분 동기 HTTP 호출로 시작한다.“주문 생성 API 안에서 알림/포인트/메일을 순서대로 호출하면 되지.”근데 서비스가 커질수록,한 서비스의 장애가 다른 서비스까지 전파되고요청 응답 시간이 일관되지 않고“이건 사실 비동기로 처리해도 되는 일인데…”라는 생각이 쌓인다.그 지점에서 가볍게 고려해볼 수 있는 도구 중 하나가 Redis Pub/Sub였다.이 글은,Redis Pub/Sub이 어떤 구조로 동작..
“캐시는 어렵지 않은데, 잘못 붙이면 더 큰 장애 포인트가 된다.” 이 글을 쓰게 된 계기Spring 기반 백엔드에서 Redis를 캐시 용도로 붙이기 시작했을 때, 솔직히 이렇게 생각했다.“DB 쿼리 전에 Redis 한 번 보고, 없으면 DB 조회해서 넣으면 끝 아닌가?”처음에는 진짜로 그 정도만 해도 성능이 꽤나 좋아졌다.조회 수가 많은 API에 캐시를 한 번 둘러줬더니, DB 커넥션 수가 눈에 띄게 줄고 응답 시간도 안정적으로 떨어졌다.문제는 그다음이었다.캐시 갱신 타이밍이 꼬이면서 유저에게는 이미 삭제된 데이터가 계속 보이고특정 키의 TTL이 한꺼번에 만료되면서 캐시 스탬피드가 터지고여러 서비스에서 같은 Redis를 쓰다 보니 키 충돌과 메모리 압박이 슬슬 보이기 시작했다.그때부터 “그냥 Redis..