분류 전체보기
![[마이카마스터] 인덱스와 캐시를 이용한 측정에 의한 성능 개선](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbSZwpq%2FbtssN4zJriK%2FfZq6mFmjEZDNpWzHg8vEZ1%2Fimg.png)
[마이카마스터] 인덱스와 캐시를 이용한 측정에 의한 성능 개선
상황 안정적인 서비스 운영을 위해선 모니터링 툴이 필수적이라 생각했고, 이에 따라 마이카마스터에 리소스 모니터링을 위해 prometheus를, APM으로는 Pinpoint를 적용했다. 적용 이후 Pinpoint로 API들의 응답 속도를 확인해보니, 성능 개선이 필요한 API들을 확인할 수 있었다. 그리고 이 중 응답속도 및 중요도를 고려해 우선순위를 설정했고, 결과적으로 지도 조회 API부터 개선하기로 결정했다. 병목 분석 먼저, 정확한 병목부터 분석하기로 했다. 지도 조회는 '대리점 목록 조회 쿼리'와, '카마스터 조회 쿼리'로 이루어져 있다. 지표 분석을 통해, 이 중 '대리점 목록 조회 쿼리'가 병목임을 확인했고, 이 쿼리부터 개선하고자 했다. 병목 제거 - 인덱스 이를 위한 수단으로 인덱스와 캐시..
![[마이카마스터] 비동기 처리를 통한 구매 상담 신청 API 개선](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbd5U7Y%2FbtssGy24jyL%2FLAndrB1iWmy6l6pmliZmxK%2Fimg.png)
[마이카마스터] 비동기 처리를 통한 구매 상담 신청 API 개선
상황 견적서 확정 이후 구매 상담 신청시, 클라이언트에게 신청 확정 메일을 보내주고 있었다. 그런데 이 요청을 처리하는데 약 3 ~ 4초 라는 시간이 걸리고 있었고, 이로 인한 전체적인 서버 성능 저하가 우려되었다. 따라서 메일 서비스의 성능을 개선하고자 했다. 문제 분석 먼저 정확한 병목 구간을 파악하고자 했다. Pinpoint를 이용한 분석을 통해, 병목 구간이 어플리케이션 서버에 존재하는 것을 확인했는데, 이는 메일 전송이 동기적으로 진행되기 때문이었다. 그리고 긴 응답 시간도 문제였지만, 더 큰 문제는 트랜잭션 점유 문제였다. 부하 테스트 결과이다. 하나의 트랜잭션 안에서 메일 전송까지 처리하다보니, 10개 뿐인 커넥션 풀은 금방 고갈되었고, 뒤에 밀려드는 요청들을 트랜잭션을 얻기 위해 기다리다 ..
[나날] 쿠폰 등록 동시성 처리를 위한 Lettuce 분산락 설정
상황 후원자분들은 캐릭터 스킨을 적용할 수 있게하기 위한 수단으로 쿠폰을 선택하였다. 이렇게 발급된 쿠폰을 앱내에서 등록하면 해당 쿠폰을 만료된 쿠폰으로 변경하는데, 동시에 여러명이 쿠폰 등록시 모두 쿠폰이 등록될 수 있는 동시성 이슈를 발견했다. 사용기술: Mysql8.0, JPA 문제 분석 @Transactional public void checkSponsor(String socialId, String code) { Sponsor sponsor = sponsorRepository.findByCode(code) .orElseThrow(() -> CodeNotExistException.EXCEPTION); // 쿠폰 유효성 확인 checkCodeAlreadyUsed(); // 쿠폰 사용 처리 confir..
![[나날] 동시 요청시 Transaction Propagation 설정으로 인한 CP Deadlock 문제](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0Cl7x%2FbtslbPXI3aB%2FTt3VGxcjdeg4GJmk3yO7v0%2Fimg.png)
[나날] 동시 요청시 Transaction Propagation 설정으로 인한 CP Deadlock 문제
문제 클라이언트로부터 동시 요청이 들어왔을때, 서버가 잠시동안 정상 동작하지 못하는 상황이 확인되었다. 문제 분석 Grafana 대시보드에 Connection Timeout Count가 증가된 것이 확인되었다. 서비스 특성상 지정된 connection-timeout 내에 처리가 불가능할만큼의 트래픽이 발생하지는 않았을 것이라 생각했고, Deadlock 발생으로 인한 문제를 예상하며 서버 로그를 확인하였다. // 스레드가 DB 커넥션을 요청한 시점으로부터 connection-timeout 만큼 지났을때 발생하는 로그들 HikariPool-1 - Connection is not available, request timed out after 5000ms. [CannotCreateTransactionExcept..
![[나날] 프록시 내부 호출을 고려한 트랜잭션 범위 최소화](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDUcYG%2Fbtskg7707GU%2F8F6FyCuHUcnMWMu0Er7Kc1%2Fimg.png)
[나날] 프록시 내부 호출을 고려한 트랜잭션 범위 최소화
문제 기존 코드에서 사용자 회원가입시에 플랫폼으로부터 사용자 정보를 요청하여 가져오는 로직이 트랜잭션안에 포함되어 있었다. 이에 따라 db 리소스가 오랜시간 점유되는 비효율이 발생했다. 문제 분석 @Service public class Auth { @Transactional public Response 회원가입_로그인(String accessToken) { // 플랫폼에서 사용자 정보 조회 ... // 회원가입 및 로그인 auth(member); // 토큰 관련 로직 ... } public void auth(Member member) { if(새로운 유저인지 체크) 회원가입 else 로그인 } } 코드를 보면, 트랜잭션이 회원가입_로그인 전체에 설정되어 실제로 트랜잭션안에 들어가지 않아도 될 부분들이 앞..

Custom Advisor 에 @Transactional 설정시 미적용 문제
@Transactional은 Spring AOP 를 사용하여 동작한다. 그럼 만약 아래와 같은 상황처럼 Custom Advisor[customAdvisor] 와 해당 Adivsor를 적용하려는 메서드[test] 에 @Transactional 설정을 아래와 같이 했을 경우 어떤 구조로 동작할까? @Service public class TestService { @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true) public void test() { log.info("Test"); } } @Aspect @Component public class AspectConfig { private final TestJpaRepository tes..
[Infra] 무중단 배포 과정에서 컨테이너 종료되지 않는 문제
문제 발생 현재 진행중인 프로젝트는 컨테이너와 nginx를 이용해서 blue-green 배포를 구현하였고, 이는 github의 특정 branch에 merge가 발생하면 일련의 과정을 거쳐 새로운 컨테이너가 생성됨과 동시에 기존 컨테이너가 내려가는 방식이다. 이렇게 무중단 배포가 실행되는 과정에서 서버의 CPU 이용률이 치솟으며 서버가 정상적으로 동작하지 않는 상황이 발생하였다. 더 문제되었던 것은 모든 무중단 배포 과정에서 이런 문제가 발생하는 것이 아니라, 규칙성없이 이런 문제가 발생하는 발생한다는 사실이었다. 원인 EC2 재부팅시에도 여전히 CPU 사용률이 치솟아 서버가 정상 동작하지 못하는 상황이 발생했는데, 이 부분과 서버 컨테이너가 두 개 동작하고 있다는 점, 그리고 EC2 재부팅시 아주 짧은 ..
[Lombok] @Builder 로 객체 생성시, 초기화 안해준 필드 null 값으로 세팅
Lombok의 @Builder 로 객체를 생성하는 경우가 종종 있을 것이다. 원하는 필드에만 값을 세팅할 수 있고, 파라미터의 순서를 고려하지 않아도 되기 때문에 상당히 편하다. 하지만 원하는 필드에만 값을 세팅할 시에, 값을 세팅하지 않은 필드에는 null 값이 들어가는 문제가 생긴다. default로 별다른 값을 설정을 하지 않았을 때는 문제가 되지 않지만, 기본 값 설정을 한 경우에는 default 값에 null 값이 덮어씌어지게 된다. 만약 이후에 해당 필드의 메서드를 호출하는 경우가 있다면 NullPointerException 이 발생할 것이다. 이를 방지하기 위한 방법으로 필드에 'final' 을 설정하면 된다. 이에 따라 초기 설정값을 보존할 수 있다. 참조 - https://velog.io..
[JPA] Cascade.REMOVE 를 이용하여 연관 관계 삭제 시도 시 발생하는 [Cannot delete or update a parent row: a foreign key constraint fails]
문제 일대다 관계가 연쇄적으로 연결된 테이블 구조에서, 부모 Entity 를 Cascade.REMOVE 를 이용하여 삭제함으로써 그 아래 연결된 자식들을 한 번에 삭제하려고 하였다. Spring Data JPA 를 사용하고 있는 상황에서, 한 번의 sql 문으로 삭제하도록 아래와 같이 네이티브 쿼리을 작성하여 호출하였다. public interface DiaryRepository extends JpaRepository { @Modifying @Query(value = "DELETE FROM diary WHERE member_id = :memberId AND write_date LIKE :likeFormat" , nativeQuery = true) void deleteByMemberAndWriteDate(..
[Docker] Error: Invalid or corrupt jarfile /app.jar
문제 발생 Docker 를 docker-compose up 을 통해 실행하려 하던 중, 위와 같은 오류가 발생하며 컨테이너 실행이 되지 않았다. 원인 및 해결 FROM openjdk:11-jdk ARG JAR_FILE=./build/libs/*.jar COPY ${JAR_FILE} app.jar/ ENTRYPOINT [ "java", "-jar", "/app.jar" ] ec2 환경에서 아래와 같이 app.jar 로 작성할 경우 /를 붙이라는 오류가 나왔기에 /를 추가해서 실행하려 했다. COPY ${JAR_FILE} app.jar/ 이 부분에서 문제가 생긴 것 이었고, app.jar/ 에서 /를 제거한 뒤에 두 개 생성되어있던 JAR_FILE(*-plain.jar, *.jar) 중에 *.jar 파일로 ..