전체 글

우아한테크코스 5기 BE 에단 Github : https://github.com/cookienc
0. 들어가기 전에 앞선 글에서 TaskScheduler 사용한 기능을 만들었다. 그중 WAS가 많아지면 생길 Race Condition 때문에 비관적 락을 적용했다. 이 부분을 테스트하기 위해 고민한 글입니다. 1. 어떻게 테스트 할까? 동시 요청을 테스트하려면 어떻게 할 수 있을까? 이를 위한 클래스가 자바에 있다. 바로 ExecutorService다. ExecutorService는 쓰레드 풀을 만들어 비동기적으로 동작하는 것을 돕는 클래스이다. 자세한 방법은 코드로 알아보자. @DisplayName("다수의 스케줄이 동시에 실행되도 ReviewCount는 1개만 증가한다.") @Test void finishReview_when_multiple_request() throws InterruptedExc..
0. 들어가기 전에 TaskScheduler를 활용해 자동적으로 리뷰 완료 상태로 변경하는 기능을 만들었습니다. 1. 필요한 이유 리뷰 랭킹을 구현하고 나니, 리뷰했지만 리뷰 완료 버튼을 누르지 않은 리뷰어들이 많았다. 글 상태가 리뷰 진행중이라고 되어있고, 리뷰 개수가 증가하지 않아 랭킹에 못 들어간 리뷰어들이 많았다! 또한, 리뷰어 평가도 이루어지지 않았다. 이 문제를 해결하기 위해 회의를 한 결과 리뷰 진행 중이면서 마감 기한이 지나면 3일 뒤에 자동으로 리뷰 완료 상태로 변경되도록 정책을 변경하기로 했다. 2. 구현 아이디어 그럼 어떻게 구현해야 할까? 가장 먼저 생각나는 건 아래처럼 스케줄러를 사용해서, 1분마다 조건에 맞는 게시글을 찾아 상태를 바꿔주는 것이다. @Scheduled(cron =..
0. 들어가기 전에 Redis를 도입하면서 테스트 방법이 필요했는데 이에 대해 고민한 글입니다. 1. Redis 테스트는 어떻게 해야할까? Reids를 도입하면서 테스트를 어떻게 해야할지에 대한 고민이 생겼다. 기존에는 MySQL 대신에 embeded h2를 사용해서 테스트를 했다. 하지만 redis를 도입하면서 이 방법은 사용할 수 없게 되었다. 찾아보니 레디스를 로컬에서 테스트하는 방법은 두 가지 방법이 있었다. 1.1 Embedded Redis //spring-data-redis compile('org.springframework.boot:spring-boot-starter-data-redis') //embedded-redis compile group: 'it.ozimov', name: 'embed..
0. 들어가기 전에 RefreshToken을 처음 개발할 때 MySQL로 관리했는데, 시간적 여유가 생겨 Redis를 적용하는 방향을 고려해봤습니다. 1. 기존 RefreshToken의 문제점 우리 바톤팀은 Jwt를 사용해서 로그인 기능을 구현했다. Jwt를 사용해서 서버의 부담을 줄이는 것은 좋았지만, AccessToken이 만료되었을 때 로그인이 풀리는 현상이 있었다. 이 문제를 해결하기 위해 RefreshToken을 도입했다. 그때는 기능 개발할 게 많아 MySQL을 통해 RefreshToken을 관리했었다. 이러다 보니 Jwt의 장점이 무색해졌다. 세션과 달리 Jwt는 서버가 무 상태이기 때문에 대량의 요청을 받았을 때 성능이 더 좋다. 하지만 로그인이 풀린다는 Jwt의 문제점을 해결하고자 도입한..
0. 들어가기 전에 예전에 진행하던 프로젝트를 유지보수하던 중에 CORS 정책이 wildcard로 열려있는 것을 확인해 보안을 위해서 wildcard를 없애던 중 마주쳤던 문제입니다. 1. AS-IS @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*"); } 기존 Cors관련 메서드는 이런 식으로 와일드 카드로 열려있었다. 와일드 카드는 보안 상 안좋기도 하고 나중에 쿠키를 사용하려면 변경해야하기 때문에 이번 기회에 아래처럼 변경해보기로 했다. @Override public void addCorsMappings(CorsRegistry registry) { reg..
0. 들어가기 전에 LazyConnectionDataSourceProxy을 MySQL Replication 할 때 사용했는데, 어떤 원리로 동작하는지 알아보기 위해 글을 작성했습니다. 1. LazyConnectionDataSourceProxy란? LazyConnectionDataSourceProxy는 JDBC 커낵션이 실제 필요한 시점에 커넥션을 가져오도록하는 프록시 객체이다. 예시 코드로 살펴보자. @Service @Transactional public class LazyService { private final DataSource dataSource; public void lazy() { HikariPoolMXBean hikariPool; if (dataSource instanceof LazyConn..
0. 들어가기 전에 추석 연휴 동안 우리 프로젝트의 db가 다운이 되었다.) 다운된 시점 근처에서 해외에서 악의적 요청을 보낸 로그가 있어서 마음을 졸였다. 다행이도 별 문제는 없었지만, DB가 하나인 상황이라 DB가 죽으면 서비스를 운영할 수 없다. 따라서 SPOF문제를 해결하기 위해 replication을 적용하기로 했다. 1. Replication 이란? 하나의 DB 서버를 다른 DB로 복제 하는 것 Replication은 하나의 DB 서버를 다른 서버로 데이터를 동기화하는 것을 의미한다. 예전에는 원본 데이터 서버 - 복제된 데이터 서버의 관계를 마스터(Master) - 슬레이브(Slave)라고 했지만 최근에는 소스(Source) - 레플리카(Replica)라고 말하는 추세이다. 소스 서버에서 데..
[Database] 클러스터링 인덱스와 논 클러스터링 인덱스 0. 들어가기전에 자주 나오는 인덱스 개념인 클러스터링 인덱스와 논 클러스터링 인덱스에 대해서 알아보았습니다. 1. 클러스터링 인덱스 MySQL InnoDB에서는 클러스터링 인덱스를 항상 사용한다.보통 테이블의 PK에 적용이 되는 인덱스이며, PK가 없으면 not null + unique한 컬럼에 사용이 되며, 이마저도 없으면 임의의 값으로 MySQL이 만들어서 사용한다. 그래서 항상 InnoDB를 사용하는 테이블에는 클러스터링 인덱스가 적용되어 있다고 할 수 있다. 그렇다면 왜 이런 방식을 사용하는 걸까? 그 이유는 검색 속도가 빠르기 때문이다. 클러스터링 인덱스는 테이블을 물리적으로 정렬을 한 인덱스이다. 즉, PK가 있다면 PK 기준으로..
쿠엔크
기러기는 기록기록