Server 121

Spring - Kafka Producer, Consumer 설계하기!

아래는 이벤트 처리를 위해 Kafka Producer, Consumer를 설계하고 적용한 내용을 정리한 것이다. Kafka 자체에 대한 내용은 이전 포스팅을 참고하자. 참고: https://jaehoney.tistory.com/197 비즈니스 설명 필요한 비즈니스는 아래와 같이 표현할 수 있다. 메일 API가 사용자에게 요청을 받아서 발송 서버로 요청을 한다. 발송 서버는 메일을 발송한 후 비동기 이벤트를 통해 Kafka로 메시지를 전파한다. Consumer는 해당 메일 정보를 받아서 사용자 설정(Archive 설정)에 따라 메일을 영구히 보관한다. Kafka 설정 Kafka에서 Producer, Topic, Consumer에는 수 많은 설정이 있다. 해당 설정들은 성능, 가용성에 엄청난 차이를 불러온다..

Server/Spring 2023.04.17

Spring - @Component가 동작하지 않는 이슈?! (Bean과 Component 차이)

어느날 AOP를 활용한 샤딩 라이브러리를 개발하던 중에 버그가 발생했다.아래는 개발한 라이브러리의 일부이다.@Component@Aspectpublic class ShardAspect { private final DataSourceFactory dataSourceFactory; @Before("@within(org.springframework.transaction.annotation.Transactional)") public void setDataSources(JoinPoint joinPoint) throws SQLException { // 구현 }}문제는 해당 라이브러리가 API 모듈에서는 동작했는데, 컨슈머 모듈에서는 동작하지 않았다.디버깅을 했는데 생성자 쪽 브레이크..

Server/Spring 2023.04.17

스프링 배치(Spring Batch) 이해하기!

Spring Batch 자바에서는 표준으로 제공하는 일괄 처리(batch)를 위한 기술이 존재하지 않았다. 스프링 배치(Spring Batch)는 이러한 문제를 해결하기 위해서 Spring Source와 Accenture가 공동으로 개발하여 탄생했다. (Accenture는 배치 아키텍처를 구현하면서 쌓은 기술적인 경험과 노하우를 가진 기업) 배치(Batch) 활용 사례 아래의 처리가 필요할 때 배치를 사용할 수 있다. 주기적으로 배치 프로세스를 커밋 적당한 양의 데이터로 분할 처리 동시 다발적인 Job의 병렬 처리 의존 관계가 있는 step 여러 개를 순차적으로 처리 조건적 Flow 구성을 통한 체계적이고 유연한 배치 모델 구성 반복, 재시도, Skip 처리 작업의 진행상황 및 로그 추적 Batch P..

Server/Spring batch 2023.03.27

SpringBoot - zip 압축 및 다운로드 구현하기!

Spring 프로젝트에서 zip 다운로드를 구현한 내용을 공유한다. 요구사항은 아래와 같았다. 사용자로부터 GET 요청을 받으면 파일 시스템 내의 특정 폴더의 파일들을 zip 형태로 내려준다. Content-Type / Accept 스펙 설계 API를 설계하면서 Content-Type과 수용 가능한 Accept 설계가 필요하다. 아래의 두 가지 중 선택에 고민이 있었다. application/zip application/octet-stream 아래 부분 참고했을 때 application/zip이 IANA에 공식적으로 등록된 MIME 표준이라서 가장 적합한 솔루션이라고 한다. 참고 - stackoverflow 추가로 아래의 이유가 있어서 application/zip을 선택했다. zip 이외의 다운로드가 추..

Server/Spring 2023.03.10

Spring - 멀티 모듈을 적용하면서 (+ CQRS, 이벤트 기반 아키텍처 적용)

최근 사이드 프로젝트에서 멀티모듈을 적용하면서 생긴 문제점들과 해결 과정을 공유하고자 한다. 기존의 싱글 모듈 프로젝트를 아래 네 개의 모듈로 분리할 수 있었다. 멀티 모듈을 적용한 부분과 이벤트 기반 아키텍처를 적용한 부분에 대해 다룬다. 멀티 모듈 아래는 멀티 모듈을 적용해보게 된 이유에 대해 설명한다. 1. Write Back (주기 반영) 조회가 1회 발생할 때마다 조회 수를 매번 Update문으로 갱신하면 DB에 부하가 매우 커질 것이라고 판단했다. 쓰기 락으로 인해 처리량 감소 -> DB 커넥션 쌓임 TPS 저하 및 DB 서버 부하 상승 그래서 Write Back을 해서 일정 주기로 DB에 반영할 수 있도록 작업이 필요했다. 즉, Scheduler가 필요했다. API에 Scheduler를 추가..

Server/Spring 2023.01.25

Spring - Servlet과 Spring의 차이!

사실 Servlet과 Spring은 정확한 비교 대상은 아닙니다. 그래서 Servlet과 Spring으로 Servlet을 다루는 것 정도로 이해해주시면 감사하겠습니다. Servlet 처음 웹 서버는 클라이언트 요청에 의해 정적인 컨텐츠만 응답할 수 있었다. 그래서 웹 서버에 프로그램을 붙여서 동적인 페이지를 시작했다. 서블릿도 동적인 페이지를 만들기 위해 웹서버에 붙이는 프로그램 중 하나이다. 만약 이러한 Client 요청이 들어왔을 때 HTTP 원문을 파싱해서 Server Response처럼 HTTP 원문을 만들어서 응답해야 한다면 개발이 힘들 것이다. 모든 규약을 확인한다. 긴 텍스트로 들어온 요청을 분석한다. 거기에 맞는 처리를 한다. 처리한 결과를 규약에 맞춰서 응답으로 보내준다. HttpServ..

Server/Spring 2022.11.16

Spring - 의존성 주입의 3가지 방법 비교!

의존성을 주입하는 방법은 총 3가지가 있다. Field Injection Setter based Injection Constructor based Injection 사실 생성자 주입이 좋다고는 다들 알고 있을 것이다. 그렇다면 왜 생성자 주입이 좋을까? (해당 부분을 더 자세히 정리하고자 포스팅한다.) Field Injection Field Injection은 의존성을 주입하고자 하는 필드에 @Autowired 애노테이션을 붙이면 된다. @RestController public class MemberController { @Autowired private MemberService memberService; } 필드 주입 방식은 아래와 같은 절차로 동작한다. 주입받으려는 빈의 생성자를 호출하여 빈을 찾거나..

Server/Spring 2022.11.08

JUnit - Private method 테스트하기! (feat. Kent Beck)

서비스 단위 테스트를 작성할 때 발생할 수 있는 모든 예외 케이스에 대해 테스트를 하려고 한다. 그러다가 private method를 테스트하고 싶을 때가 있다.어떻게 처리할 수 있는 지 알아보자. 아래는 예시로 사용할 class이다.public class Magician { private int level; private int exp; private void levelUp() { if(exp >= 100) { int count = exp / 100; this.level += count; exp -= 100 * count; } }}Reflection을 활용한 테스트리플렉션을 활용하면 private ..

Server/JUnit, Spock 2022.11.05

Spring - @Transactional(readOnly = true)을 하면 일어나는 일

왜 Service 클래스 단위에 기본적으로 @Transactional(readOnly = true) 속성을 사용할까? @Trasnactional(readOnly = true)를 사용하면 어떤 점에서 이득이 있는 지 알아보자. 예상치 못한 엔터티의 등록, 변경, 삭제 예방 @Transactional에 readOnly = true 옵션을 주면 스프링 프레임워크가 세션 플러시 모드를 MANUAL로 설정한다. 이렇게 하면 강제로 플러시를 호출하지 않는 한 플러시가 일어나지 않게 되어서, 트랜잭션이 커밋되면서 실수로 엔터티가 등록, 수정, 삭제 되는 일을 방지한다. 성능 최적화 1. 트랜잭션을 읽기 전용으로 열면 JPA에서 제공하는 스냅샷 저장이나 변경 감지 등을 사용하지 않아서 자원(CPU, Memory)의 낭..

Server/Spring JPA 2022.11.04

Spring - consumes와 produces 이해하기!

스프링에서 동일한 URL인데 Content-Type 헤더에 따라 다른 Controller method를 실행시키려면 아래와 같은 RequestMapping 애노테이션의 consumes 속성을 사용한다. @PostMapping(path = "/resources", consumes = MediaType.APPLICATION_JSON_VALUE) 그 뿐만 아니라 Content-Type에 대한 제약을 걸 때도 consumes를 사용하는데, produces 속성과 헷갈리게 되는 경우가 많다. 그래서 consumes는 produces와 어떻게 다른 지 알아보자! consumes 해당 애노테이션의 RequestMapping.consumes의 속성에 대한 description을 확인해봤다. 해당 내용을 번역하면 '미디..

Server/Spring 2022.11.02