전체 글 232

헥사고날 아키텍처 적용기

https://velog.io/@onyx01/%ED%97%A5%EC%82%AC%EA%B3%A0%EB%82%A0-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98%EB%A1%9C-%EC%BD%94%EB%93%9C-%EA%B5%AC%ED%98%84-%ED%95%B4-%EB%B3%B4%EA%B8%B0 헥사고날 아키텍처로 코드 구현 해 보기헥사고날 아키텍처 (Hexagonal Architecture) 를 구현 해 보면서 이해한 개념을 정리 하고, 소감을 남겨봅니다.velog.io 본 글은 위 링크의 글을 참고하여 작성하였습니다.레이어드 아키텍처와의 비교레이어드 아키텍처- 소프트웨어 시스템을 계층으로 나누어 설계하는 전통적인 방식이다. 일반적으로 표현 계층(Presentation Layer), 비..

메시지 큐 도입기 - 비동기 로깅 처리 및 알림 기능 (RabbitMQ, Kafka, Redis Pub/Sub 비교)

https://f-lab.kr/insight/message-queue-system-comparison 메시지 큐 시스템 비교: Kafka, RabbitMQ, Redis Pub/SubKafka, RabbitMQ, Redis Pub/Sub 세 가지 메시지 큐 시스템의 특징, 장단점 및 적합한 사용 사례를 비교 분석합니다.f-lab.kr본 글을 보고 정리한 내용입니다. 메시지 큐 도입기왜 도입을 하는가?  서비스의 확장성과 성능 최적화를 위해 메시지 큐(Message Queue)를 도입하여 비동기 로깅 처리 및 알림 기능을 구현하려고 한다.기존 로그 저장 방식은 (Logback → 파일)로 저장하였다. 로그가 서버에서 Logback을 통해 파일(server.log, error.log)에 저장하고 Promtai..

로그 파일 Grafana+Promtail+loki 이용해서 실시간 모니터링 적용하기

Grafana+Promtail+loki 를 사용한 이유로그 수집을 하기 위한 기술을 뽑으자면 ELK(Elasticsearch, Logstash, Kibana)를 떠올릴 수 있다.하지만 서버 스펙의 한계(Ec2 프리티어)로, 비교적 가볍게 실행할 수 있는 PromTail, Loki, Grafana를 도입하게 되었다. 모니터링 서버는 다음과 같다. 모니터링 서버에는 Grafana, Loki를 도커로 띄우고, 운영 서버에는 Promtail과 스프링 부트가 도커로 돌아가게 된다. 모니터링 서버를 분리한 이유는 Promtail, Grafana, Loki 같은 로그/메트릭 수집 도구는 많은 I/O와 네트워크 트래픽을 발생시키기 때문에 분리하였다. (모니터링 서버)에 Grafana, Loki 도커로 실행하기docke..

N+1 문제 해결하기 (@EntityGraph 사용)

@EntityGraph란?연관관계가 지연 로딩으로 되어있을 경우 fetch 조인을 사용하여 여러 번의 쿼리를 한 번에 해결할 수 있습니다.@EntityGraph는 Data JPA에서 fetch 조인을 어노테이션으로 사용할 수 있도록 만들어 준 기능입니다.  N+1 발생 이유기본적으로 @OneToMany, @ManyToMany 관계는 Lazy Loading으로 되어 있는 경우JPA에서 @OneToMany와 @ManyToOne 관계 등을 지연 로딩(Lazy)으로 설정한 경우,  연관관계에서 종속된 엔티티는 쿼리 실행 시 select 되지 않고 proxy 객체를 만들어 엔티티가 적용시킵니다. 그 후 해당 proxy 객체를 호출할 때마다 그때 그때 select 쿼리가 실행됩니다. EnttiyGraph 를 사용한..

Jacoco를 이용한 테스트 커버리지 측정후, 보완하기

왜 적용했는가?현재 테스팅을 통해 컨트롤러, 서비스, 도메인, 레포지토리 단에서 코드를 짜고 있다.내 테스트 코드가 얼마나 실제 도메인을 커버를 하고 있는지, 좋은 테스트를 짜고 있는지 궁금하여 Jacoco를 도입하였다. Jacoco란?JaCoCo는 단위 테스트 또는 통합 테스트를 실행하면서 어떤 코드가 실행되었는지 분석하고 커버리지 리포트를 생성해준다. 이를 통해 테스트가 충분히 작성되었는지 확인하고, 테스트 누락된 부분을 보완할 수 있다. Build.gradleplugins { id 'jacoco'}jacoco { toolVersion = "0.8.8" reportsDirectory = layout.buildDirectory.dir('customJacocoReportDir')}test { finali..

스프링 인터셉터(Spring Interceptor)로 API로그 DB에 저장하기

왜 적용했는가?기존 AOP를 통해 모든 API 호출에 대한 로깅을 진행하였다.그런데 PR 리뷰를 받던 중, 다음과 같은 피드백을 받게 되었다.1. 맞지 않는 URL로 요청을 보내는 경우2. Http Method를 이상하게 보내는 경우아예 Pointcut으로 지정한 컨트롤러 메서드를 타지 않기 때문에 로깅이 전혀 불가능하다.또한 치명적인 문제는, 컨트롤러에서 @Valid 어노테이션 조건을 걸어놓은 경우 AOP가 작동하지 않는다. (Valid 여부가 컨트롤러 호출보다 먼저 실행)따라서 본 프로젝트에는 AOP에서 Interceptor로 로깅 요청을 변경하였다. Interceptor로 변경하기프로젝트의 log 도메인이다. LoggingInterceptor와, RequestBodyWrappingFilter로 구분..