전체 글

우아한테크코스 5기 BE 에단 Github : https://github.com/cookienc
0. 들어가기 전에무중단 배포의 필요성을 느끼게 되어서 도입하면서 생각한 점을 정리했습니다.1. 왜 무중단 배포를 진행하는가?사실 지금까지는 CI/CD가 되어있어서 무중단 배포를 할 필요를 못느꼈다. 하지만 이제 사용자를 모집하려고 하고 있고, 계속해서 개발할 기능들이 많이 있기 때문에 사용자 경험 때문에 무중단 배포가 필요했다.2. 과정바톤 프로젝트와 마찬가지로 블루 그린 배포를 해줄 예정이다. 순서는 다음과 같다.포트가 다른 새로운 컨테이너를 띄운다.nginx를 사용해서 healthcheck를 한다.정상적으로 생성이 되었다면 nginx reload -s로 클라이언트 요청을 옮겨준다.old 버전 컨테이너를 삭제한다.3. 코드먼저 CD 로직이 있는 github actions 설정파일 수정해줬다.기존에는..
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 */..
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)라고 말하는 추세이다. 소스 서버에서 데..
쿠엔크
기러기는 기록기록