[gradle] 멀티모듈에서 컴포넌트 스캔이 되지 않는 문제
·
스프링 부트/오류
현재 클린 아키텍처를 학습하기 위해 코틀린을 통해 간단한 프로젝트를 진행하고 있으며, 파사드 패턴과 포트/어댑터 패턴을 적용한 헥사고날 아키텍처를 구현하려고 노력 중에 있다. 그리고 해당 과정에서 스프링 어플리케이션이 컴포넌트 스캔을 제대로 하지 못하는 문제를 발견하였고, 이를 성공적으로 해결하였다. 설명하기에 앞서서, 앞으로 설명하고자 하는 프로젝트는 총 5개의 모듈을 구축해서 운영하고 있으며, 모듈이 가지는 책임은 다음과 같다:domain: 순수 코틀린으로 이루어진 모듈independent: 모든 모듈에서 공통적으로 쓰이게 되는 모듈infra:persistence-db: JPA 관련 로직으로 이루어진 모듈infra:security: Spring Security 관련 로직이 이루어진 모듈(토큰 발급에 ..
코틀린에서 JPA 적용하기
·
스프링 부트/Kotlin
최근 들어 실무 진영에서는 코틀린에 대한 선호도가 높아지고 있는 상황으로 보인다. 당장 올해 여름에 진행했던 당근 테크 인턴십의 서버 직군만 보더라도, 코틀린과 Spring 프레임워크를 활용하는 개발자들을 원했다. 또한 상당수의 빅테크 기업이 여러 서비스를 점차 자바가 아닌 코틀린을 활용해서 개발하거나, 기존의 서비스를 코틀린으로 마이그레이션 하는 것을 볼 수 있었다. 더 이상 코틀린은 선택이 아닌 필수라고 생각했다. 그래서 최근부터 코프링(Kotlin + Spring Framework)을 공부하고 있는데, 해당 과정에서 JPA를 적용하면서 겪은 과정을 풀어내보려고 한다. 코틀린과 궁합이 좋지 않은 JPAJPA는 자바 진영에서 ORM 기술 표준으로 사용되는 인터페이스의 집합체이고, 이를 구현한 것이 Hi..
[Spring Security] 스프링에서 CORS를 해결하는 또다른 방법
·
스프링 부트/오류
개발을 시작한 지 얼마 되지 않은 개발자들이 가장 마주치기 싫어하는 오류가 무엇일까? 난 당당하게 CORS라고 답해주고 싶다. 본인도 처음 프로젝트를 도전했을 때도 결국 CORS 때문에 API 연결에 실패해 마무리하지 못한 슬픈 기억을 가지고 있다. 그만큼 CORS는 웹 개발자라면 가장 먼저 넘어야 할 산이라고 불린다고 해도 과언이 아니다. 평소에 관심을 가지고 있었던 스벨트 프레임워크를 통해 간단한 어드민 관리자 페이지를 구현하는 도중, API를 서버와 연결하는 과정에서 CORS 오류를 마주치고 말았다. 개발을 본격적으로 시작한 지 어연 1년 하고도 6개월이 지났지만, 아직도 CORS의 늪에 빠져 허우적댈 줄은 꿈에도 몰랐다.. 심지어 이번에는 백엔드 개발자의 입장이 아닌, 프런트엔드 개발자의 입장에서..
ElastiCache과 Redisson을 통해 스프링 부트에서 무형 객체 캐싱하기
·
스프링 부트/Java
원격 웨이팅 서비스에서 가장 많이 동작하는 API는 무엇일까? 놀랍게도 조회 API이다. 하루에도 수천 명의 사용자는 수십 개의 매장을 살펴보며 메뉴를 구경하고, 마음에 드는 곳을 발견하면 웨이팅을 걸고는 한다. 라인업지도 그랬다. 만약, 서비스를 접속했는데 주점 목록을 가져오는 데 수 초 이상이 걸린다면 어떻게 될까? 물론 서비스 사용자 수가 적을 때에는 문제가 없겠지만, 축제 기간에 수 백~수 천 명의 사용자가 초 단위로 접속하면 당연히 DB에는 부하가 갈 것이고, 부하가 가면 랜딩 페이지를 가져오는 데에는 오랜 시간이 걸릴 것이다. 사람들이 웹사이트를 처음 보고 해당 웹사이트가 어떤지 평가하는 데 걸리는 시간은 50m/s 이내(20분의 1초)라고 한다. 따라서 랜딩 페이지에서 데이터 로딩이 지연되는..
AuroraDB와 @Transactional 어노테이션을 통한 간단한 CQRS 구현하기
·
스프링 부트/Java
또 라인업지다. 혹시 라인업지가 무엇인지 궁금하신 분들을 위해 간단히 설명하자면, 2024년 가천대학교 가을 축제에 사용된 원격 웨이팅 서비스이다. 그리고 이 서비스를 구현하기 위해 경험했던 기술적 도전들을 차례차례 풀어나가고 있으며, 이번 글은 AuroraDB와 @Transactional 어노테이션을 통한 간단한 CQRS를 구현하는 내용이 될 것이다! CQRSCQRS(Command and Query Responsibility Segregation)는, 데이터 저장소(DB)로부터 발생하는 읽기 작업과 쓰기 작업을 분리하는 것을 뜻한다. 간단히 말해, 조회(R)와 명령(CUD) 작업을 분리한다는 것이다. 대부분의 서비스는 쓰기 작업보다 조회 작업이 압도적으로 많이 발생하기 때문에, 저장소를 분리하여 조금이..
@Valid 검증 예외 처리를 통한 공통 응답 보내기
·
스프링 부트/Java
현재 리드를 역임하고 있는 가천대학교 IT학술동아리 Leets의 5기 새 단장(?)을 맞아, 랜딩 페이지에 신기능을 도입하는 중이다.신기능이라고 해봤자 거창한 것은 아니고, 모집 알림 신청 기능을 메일링을 통해 구현해주는 것이 목표이다! 이번 글은 해당 기능을 구현하면서 DTO에서 필드 검증 시에 발생하는 예외를 어떻게 처리하여 프런트에게 공통 응답을 보내줄 수 있었는지에 대한 내용이 될 것이다.덕분에 오늘도 프런트랑 행복한 협업을 진행할 수 있게 되었다..>_ DTO에서 필드 검증하기DTO를 통해 필요한 값을 전달 받을 때, 프런트에서도 검증을 해주지만 혹시 모를 경우에 대비해 서버 단에서도 검증을 해주는 것이 좋다.이를 위해서 우리는 @Valid 어노테이션을 사용해야 한다. @Valid@Valid 어..
AOP 로깅을 통한 효율적인 로깅 로직 구현하기
·
스프링 부트/Java
이번에도 라인업지 서비스를 진행하면서 적용했던 기술적 도전을 간단하게나마 풀어보려 한다.매번 라인업지 서비스를 가져와서 '또 라인업지야?'라고 느끼실 수 있을 것 같다고 생각한다.하지만 그만큼 해당 프로젝트가 필자로 하여금 수많은 기술적 도전을 통해 한층 더 성장하게 만들어 주었기에, 다양한 문제를 해결하며 얻은 교훈과 성장의 흔적들을 여러 글에 걸쳐 정리해보려고 하는 것이니 이해해 주시면 정말 감사하겠다ㅎㅎ 🥹 그럼 각설하고, AOP 로깅을 적용하게 된 계기를 우선 말씀드리면서 시작하겠다. AOP 로깅의 적용 계기와 기존 로깅 로직의 한계점우리가 보통 로깅을 비즈니스 로직에 적용한다고 하면, @slf4j 어노테이션을 통해 비즈니스 로직에 다음과 같은 코드를 끼워 넣어 다음과 같이 구현한다. 해당 코드..
[Kotlin] Spring Security에서 코틀린 DSL 적용하기
·
스프링 부트/오류
Spring Security에 Kotlin DSL을 사용했을 때 빌드가 되지 않는다...Kotlin으로 Spring Security 개발을 하던 중, 공식 문서와 동일한 코드인데 IntelliJ에서는 빌드가 되지 않는 오류가 계속 발생했다.. 코틀린 DSL과 자바와의 가장 큰 차이점을 꼽아보자면,자바는 람다 체이닝 메서드(`.`)을 통해 매개변수를 구현해 주지만,코틀린은 DSL을 통해 매개변수를 구현해 준다는 것이었다.근데 DSL이 대체 무엇일까? DSL(Domain Specific Language)DSL은 도메인 특정 언어, 쉽게 풀어 말하자면 특정 도메인에 국한된 문법이라고 생각하면 된다. 이를 통해 우리는 특정 도메인의 내부 로직 및 메서드를 추상화하여 가독성을 높이고 재사용 및 유지보수성을 높일 ..
[JPA] 양방향 매핑을 지양해야 하는 이유
·
스프링 부트/Java
관습적으로 개발한 결과물무심코 스프링 부트와 JPA를 통해 개발을 하다 보면, 편리함에 녹아들어 테이블 간 연관관계를 막무가내로 설정하고는 한다.당장 본인도 그랬다..주로 양방향 매핑을 통해 개발하는 이유는 다음과 같다.개발의 편의성을 증진시키기 위해비즈니스 로직을 작성할 때, 양쪽 엔티티에서 원하는 객체를 쉽게 가져올 수 있어서물론 양방향 매핑을 통해, 개발하는 데 있어서 정말 많은 이점을 가져갈 수 있다고 생각했다. 특정 객체와 연관된 객체들을 손쉽게 가져온다거나, 단순 조회를 위해 여러 객체들을 가져올 때 덕분에 시간을 정말 아낄 수 있었다. 그러면 왜 그러한 이점을 버리면서까지 양방향 매핑을 지향한 걸까? 양방향 매핑이 가져다주는 문제점순환 참조만약 두 엔티티가 서로를 참조하게 될 경우, JSON..
[JPA] ExecutorService를 통한 엔티티가 변경되지 않는 않는 오류
·
스프링 부트/오류
가천대학교 가을 축제 웨이팅 서비스 라인업지를 개발하면서, 우리 서비스는 노쇼 방지를 위해 자동 취소 로직을 구현해야 할 필요가 있었다. 다만 단순한 '자동 취소'를 구현하는 것이 아닌,자동 취소 시 주점의 대기 팀 숫자가 감소해야 함자동 취소는 호출 이후 특정 시점 이후에 동작해야 함자동 취소 시, 사용자한테 알림톡으로 취소되었다고 알려주어야 함이런 정책들을 고려하면서 로직을 구현해야 했고, 이를 위해 ScheduledExecutorService를 도입하였다. ScheduledExcutorServiceScheduledExecutorService는 원하는 작업(메서드)를 특정 시간 이후에 동작하도록 설정할 수 있는 ExecutorService의 일종이다.ScheduledExecutorService는 총 ..