분류 전체보기
Spring Batch 통합 테스트 환경 구축하기
Spring Batch 통합 테스트 환경 구축하기
2022.08.03서론 앞으로 팀내 스프링 배치를 적극 사용하기 위해, 미리 테스트 환경 구축하는 작업을 진행했던 내용에 대해서 공유해보려고 합니다. 작업 하기 전 스프링 배치 테스트는 어떤식으로 하는게 좋을지 검색을 해봤습니다. 이쉽게도 스프링 배치는 아티클이 별로 없기 때문에 테스트에 대해 집중적으로 다루고 있는 글도 드물었습니다. AS-IS 우선 기존에 제가 테스틀 작성했던 방법입니다.(과거 배치 테스트 블로그 글에서 소개했던 방법을 그대로 사용했었습니다) @SpringBatchTest @SpringBootTest(classes = {GetProductDtoJobConfig.class, TestBatchConfig.class}) class GetProductResponseJobConfigTest { @Autowire..
스프링 배치에서 JobParameters을 더 편하게 사용하는 방법
스프링 배치에서 JobParameters을 더 편하게 사용하는 방법
2022.06.23스프링 배치에서 JobPameter를 사용할때 외부에서 주입받아서 사용하는 경우가 많다. 대표적으로 "날짜"가 있다. 하지만 SpringBatch에서는 LocalDateTime을 지원하지 않아서 다음과 같이 타입 변환 작업이 이루어져야한다. @Bean @StepScope public ItemReader simpleReader( @Value("#{jobParameters[requestDate]}") String requestDate ) { LocalDate date = LocalDate.parse(requestDate, DateTimeFormatter.ISO_DATE); // yyyy-MM-dd log.info(">>> date = {}", date); return new ListItemReader(Lis..
opencsv를 활용한 쉽고 유연한 설계
opencsv를 활용한 쉽고 유연한 설계
2022.06.04csv파일을 이용한 대량 등록 작업을 처리하면서 opencsv를 활용한 경험에 대해서 글을 작성해보려고합니다. 고민했던 상황 csv 파일을 통해서 업로드를 진행하지만, 추후 excel을 통한 확장 가능성을 열어두고 싶었음 깔끔하고 쉽게 csv파일을 읽어오고 싶었다. opencsv를 통해서 쉽게 csv 파일을 읽을 수 있지만, 중복 코드를 제거하고 싶었음 opencsv는 csv 파일을 쉽게 객체로 변환해주는 역할을 한다. 이런식으로 쉽고 가시성있게 코드를 작성할 수 있다. final List list = new CsvToBeanBuilder(new FileReader("text.csv")) .withType(Man.class) .build() .parse(); open csv에 대해 자세한 사용 방법에 대..
MSA 환경에서 분산 추적시스템 적용하기
MSA 환경에서 분산 추적시스템 적용하기
2022.03.13서론 마이크로 서비스 환경에서는 사용자가 보낸 하나의 HTTP 요청이 내부적으로 여러 서비스를 거쳐서 응답을 제공하는 경우가 많다. 이런 이유에서 마이크로 서비스 환경에서는 요청을 추적하거나, 병목 구간을 파악하기가 힘들다. 마이크로 서비스에서 요청을 추적하는 건 매우 중요하고 필수적입니다. 이번 글에서는 zipkin & spring cloud sleuth를 활용해서 이를 관리하는 방법을 소개하겠습니다. Zipkin zipkin은 대표적은 분산 추적 시스템 오픈소스다. 흐름 구성도는 다음과 같이 구성되어있다. 리포터는 추적 데이터를 전송하고 데이터베이스에 저장하게된다. 이 데이터는 나중에 API를 통해서 스토리지에 쿼리하여 UI로 제공하게된다. 트레이서 라이브러리는 홈페이지에서 확인 가능하다. 다양한 언..
비동기 처리를 이용한 대량 쿠폰 등록 작업
비동기 처리를 이용한 대량 쿠폰 등록 작업
2022.03.09서론 설날을 대비해서 쿠폰을 이용한 프로모션 계획이 있었습니다. 프로모션 기능을 원활하게 진행하기 위해 대량 쿠폰 등록 기능을 빠르게 만들어줄 사람이 필요했고, 제가 해당 업무에 할당되어서 개발을 진행했습니다. 문제 사항 - 기존 쿠폰은 수동으로 최대 50개씩 상품이나, 브랜드를 등록할 수 있다. - 수천개의 쿠폰을 일괄 등록할 시, (상품 개수 / 50) 번의 작업을 반복해야한다. (수천개라 생각하면...) - 업무가 효율적이지 않고, 사람의 실수가 많이 발생할 수 있다. 개선 사항 - csv 파일 업로드를 통해 쿠폰을 일괄 등록을 할 수 있어야한다. 본론 해당 기능을 개발하는 도중 다른 서비스간의 통신이 필요했습니다. 그림으로 나타내면 다음과 같습니다. MSA 환경에서는 각자의 DB를 갖고 있기 때문..
Transactional REQUIRES_NEW에 대한 오해
Transactional REQUIRES_NEW에 대한 오해
2021.12.21서론예전에 함께 스터디를 했던 스터디원이 트랜잭션에 관한 블로그 글을 공유하면서, 흥미로운 내용이라고 소개했다.해당 글에서는 기존에 내가 알고있던 사실이 틀리다라고 얘기하는 내용이었다. 내가 잘못알고 있었던 건가??! 생각들때쯤 해당 코드에서 옥에 티 발견했다. 간단한 내용일 수도 있지만 개념을 확실하게 잡지 않으면 충분히 헷갈릴 수 있을 거 같다. 덕분에 나도 이번 기회에 다시 학습해보고 명확하게 정리를 해보는 시간을 갖게 되었다. 본문 글의 내용은 이런 것이었다.@Transactional을 사용할 때 전파 속성을 "REQUIRES_NEW"로 지정해도, 부모 트랜잭션이랑 독립된 트랜잭션으로 실행되지 않는다 라는 내용이었다. 이 주장의 근거로 "자식 트랜잭션에서 예외가 발생하..
Log4j 보안 이슈와 스프링 부트와의 상관 관계
Log4j 보안 이슈와 스프링 부트와의 상관 관계
2021.12.11사내에 갑자기 기사 내용을 공유하면서, log4j2에 대한 보안 이슈가 있다며, 모든 프로젝트에 대한 버전업을 진행해야 된다라는 메시지를 봤다. 기사 내용에는 log4j2를 사용하면 제로데이 공격 가능성이 있다라는 내용이었다. (기사 내용) 하지만 우리는 스프링 부트를 이용해서 프로젝트를 만들고있다. spring-boot-start-logging은 slf4j라는 로깅 인터페이스를 이용해서 로그를 찍는데, 구현체인 log4j2랑 logback을 라이브러리로 다운받는다. 그리고 구현체는 기본적으로 Logback을 이용한다. 스프링 공식 문서에도 해당 내용은 언급되어있다. By default, if you use the “Starters”, Logback is used for logging. Appropri..
Generic Type Erasure는 어떻게 타입캐스팅을 하는건가요?
Generic Type Erasure는 어떻게 타입캐스팅을 하는건가요?
2021.12.07서론 커뮤니티에 다음과 같은 질문이 올라왔다. 질문 내용은 다음과 같다. 제네릭은 런타임시 타입 소거(type erasure)를 하기 때문에, 언바운디드(unbounded) 타입 같은 경우 Object로 치환 되는데, 어떻게 클라이언트에서 선언한 타입으로 캐스팅이 되는건가요?? 쉽게 풀어서 얘기하면, 다음 코드에서 리턴 타입은 Object인데 어떻게 클라이언트에서 서브 타입으로 타입 캐스팅 없이 받냐라는 내용이다. // 리턴 타입은 Object 라면서??! public T get(T t) { return t; } 우선 타입 소거가 무엇인지 알아보자. 타입 소거 Type Erasure 다음 내용은 오라클 공식 문서에 나와있는 Type Erasure에 대한 설명 중 일부다. Generics were intr..
스프링과 EntityManager의 동시성 비밀
스프링과 EntityManager의 동시성 비밀
2021.11.20서론 최근 바빠서 항상 조금씩 끄적이면서 임시저장을 했는데 오랜만에 글을 마무리 해봅니다. 이번 글에서는 EntityManger에 대한 얘기를 해보려고합니다. 목차 EntityManager란? EntityManager가 생성되는 과정 EntityManager는 어떻게 thread-safe를 보장할까? EntityManager란 무엇일까? 공식 문서에서 EntityManager는 다음과 같이 기술되어 있다. An EntityManager instance is associated with a persistence context. A persistence context is a set of entity instances in which for any persistent entity identity there ..
다양한 도커 이미지 생성 방법 및 최적화 방법. (Spring boot)
다양한 도커 이미지 생성 방법 및 최적화 방법. (Spring boot)
2021.10.01사전 준비 스프링 부트로 프로젝트 생성한 뒤 깃헙 퍼블릭 저장소로 업로드합니다. 1. 호스트의 jar파일을 이미지에 추가하기 가장 간단한 방법입니다. 호스트 OS에서 빌드된 jar파일을 이미지에 추가합니다. Dockerfile FROM openjdk:11 LABEL topic="docker-test" ARG JAR_FILE=./build/libs/*.jar ## jar파일 변수 설정 ADD ${JAR_FILE} app.jar ## 해당 파일을 이미지에 추가한다 ENTRYPOINT ["java", "-jar", "/app.jar"] ## jar 실행 이미지 만들기 docker build -t {이미지명} {도커파일디렉터리) 저는 이미지 이름을 host-jar로 만들었습니다. 이미지가 정상적으로 생성됐는지 ..
Optimistic Lock으로 선착순 한 명 쿠폰을 만들어보자
Optimistic Lock으로 선착순 한 명 쿠폰을 만들어보자
2021.08.28개요 사내에서 쿠폰 등록 이벤트를 만들어야하는 상황이 있었다. 쿠폰은 고유의 쿠폰번호가 있으며, 해당 쿠폰은 유저당 하나만 등록할 수 있었다. (대표적으로 스타크래프트 cd키라고 생각하자). 고민했던 점 - 확장성: 쿠폰은 한 번만 등록할 수 있지만, 언제 선착순 최대 x명으로 변경될지 모른다 - 동시성: 동시에 x명의 유저들이 쿠폰을 등록한 경우 결론 - 확장성: 쿠폰의 최대 사용 개수랑, 현재 남은 쿠폰 물량으로 나눴다. - 동시성: 현재 선착순 한 명에서 Redis를 사용하면 오버 엔지니어링이라고 판단됐다. 우선 optimistic lock을 이용하고, 기획이 확장되면 필드를 제거하고 Redis를 이용한 추가 설계를 고려할 수 있다. 간단한 설계 예시 실제로는 유저가 쿠폰을 등록하는 것이지만 동시성..
@Async는 어떤식으로 실행될까?
@Async는 어떤식으로 실행될까?
2021.08.23예제 코드 @Slf4j @Service @RequiredArgsConstructor public class Producer { private final EmailService emailService; public void doSomething() { emailService.send(); log.info(">>> doSomething"); } } @Slf4j @Service public class EmailService { @Async public void send() { log.info(">>> 이메일 전송 시작"); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } log.info(">>> ..