본문 바로가기

JAVA13

밸리데이션 정책에 전략 패턴을 적용해보았다 해당 포스터는 Volunteer 프로젝트의 관한 내용입니다. 객체지향 프로그래밍에서 추상화는 많은 이점을 제공한다. 인터페이스, DI, 추상 클래스 등은 런타임에 구체 클래스가 정해지므로 유연한 확장과 의존성이 줄어든다는 점이 존재한다. 이처럼 구현을 하면서 if문 분기 처리가 많이 나오거나, 추상화가 가능한 부분이 나온다면 추상화를 이용한 패턴을 고려해 본다. 프로젝트를 리팩터링 하면서 유효성 검사에 분기처리가 필요했고, 추상화와 밀접하게 연관된 전략 패턴을 적용해 보았다. 전략 패턴의 개념은 다음과 같다. 실행(런타임) 중에 다형성을 기반으로 알고리즘 전략을 선택하여, 동적으로 전략을 수정할 수 있는 행위 디자인 패턴. 어떤 행동을 수행하는 알고리즘이 여러 개 있을 때, 동작을 미리 전략으로 정의함으.. 2024. 2. 9.
JPA saveAll()의 N+1 문제 해당 포스터는 Volunteer 프로젝트의 내용입니다. 발생 원인 JPA saveAll()를 사용할 때, Bulk Insert를 기대했으나 기대와는 다르게 엔티티 각각 INSERT 쿼리가 발생되었다. 즉, N개의 엔티티를 저장했을 때 INSERT 쿼리가 N개가 발생한다. 먼저, saveAll() 메서드 내부 구조를 조금 더 자세히 알아보자. saveAll() 메서드 내부적으로 루프를 통해 결국 save() 메서드를 사용한다. 영속성 컨텍스트에서 ID가 null(0L) 인지를 판별해서 새로운 객체임을 판단하고, 새로운 엔티티일 경우 영속화를 진행한다. 이때, INSERT 쿼리가 발생하는 것을 예상할 수 있다. (실제 DEBUG을 했을 때도 즉시 INSERT 쿼리가 발생했다.) 💡 그럼 JPA를 사용할 때,.. 2024. 2. 1.
원시값 포장과 VO 스타트업 인턴 도메인을 파악하면서 VO의 개념 정립할 수 있었고, 스스로 공부한 내용을 기록해보고자 한다. (참고로 해당 서비스는 도메인과 엔티티가 분리된 환경이였다.) 원시값 포장이란? 원시값 포장이란, String, int 등 원시 타입(Primitive)의 값을 이용해 속성을 표현하지 않고, 의미있는 객체로 포장해서 사용한다는 개념이다. 간단히 아래와 같다고 볼 수 있다. String name = "홍길동"; //안티 패턴 Name name = new Name("홍길동"); name 에는 다양한 유효성 검사 등이 존재할 수 있는데, 외부에서 검사하는 것 아니라, 이러한 검사를 Name 클래스에게 책임을 넘기게 된다. 그럼 원시값을 사용하는 이유가 뭘까? VO 라는 객체로 포장했기 때문에, 클래스 내.. 2023. 9. 23.
퍼사드 패턴을 도입해 도메인 간 의존성을 줄이다. Volunteer 프로젝트 관련 포스터 입니다. GitHub - project-Volunteer/BackEnd: 사이드 프로젝트 - 봉사 활동 팀 매칭 서비스(BackEnd)👊🏼 사이드 프로젝트 - 봉사 활동 팀 매칭 서비스(BackEnd)👊🏼. Contribute to project-Volunteer/BackEnd development by creating an account on GitHub. github.com 프로젝트를 진행하면서 필요한 도메인이 늘어나고, Service layer, Repository layer 간 의존성이 증가하는 상황이 빈번히 발생했습니다. 이러한 의존성을 줄이고 응집도 높은 클래스를 만들기 위해 퍼사드 디자인 패턴을 도입한 경험을 소개해드리고자 합니다. 레거시 상황 아래는 .. 2023. 8. 13.
Spring Rest docs 적용기 Volunteer 사이드 프로젝트에 적용하면서 학습했던 Spring Rest docs를 정리해보고자 합니다. 자세한 코드는 깃허브를 참고해주시기 바랍니다. Rest Docs 란? 테스트 코드 기반으로 Restful API 문서화를 도와주는 도구 입니다. Asciidoctor를 사용해서 AsciiDoc(adoc 파일)을 HTML 등으로 다양한 포멧으로 문서화를 변환할 수 있습니다. snippet(adoc 파일)은 문서화에 필요한 문서 조각이며, Asciidoctor가 이러한 파일을 HTML 파일 등으로 변환시켜주게 준다. 문서화를 위한 테스트 코드와 API 명세가 일치하지 않으면, 테스트가 실패하게 되고 문서화가 진행되지 않습니다. 그러므로 검증된 문서 임을 보장할 수 있습니다. 예전 프로젝트에서는 Swa.. 2023. 8. 8.
동시성 이슈에 낙관적 락을 걸어보다. 들어가기 앞서 Volunteer 사이드프로젝트를 진행하면서, 사용자는 공지사항에 대해서 읽음 표시를 할 수 있었다. 읽음 표시 및 해제가 가능하며 흔히 좋아요 기능과 같은 기능이다. 평소에 커뮤니티 서비스를 사용하면서 좋아요 버튼을 광클하면 어떻게 될까? 라는 생각을 했었고, 좋아요 기능과 비슷한 기능이 사이드프로젝트 내에 존재해 실제 무슨 일이 생길지 테스트 해보았다. 같은 사용자가 같은 공지사항의 읽음을 광클을 한다는 상황을 가정하고 Jmeter를 통해 간단히 실험해보았다. 하나의 공지사항에 대해서 같은 사용자는 한번만 읽음 확인이 가능한데, 같은 사용자의 정보 2개가 들어오는것을 볼 수 있었다. 동시성 이슈가 발생한 것이다.❗ 같은 사용자 읽음 정보가 들어왔을 때, 읽음 확인 사용자 리스트 조회 시.. 2023. 7. 8.
JPA & Querydsl exists 성능 분석 들어가기 앞서 Volunteer 사이드 프로젝트를 진행하면서 Spring Data JPA를 이용해 exists 함수를 사용해야할 상황이 있었다. Spring Data JPA는기본 메서드로 existsBy~ 형태로 제공하지만, where절의 조건이 3개,4개... 증가할 수록 필드명이 너무 길어져 @Query를 사용합니다. 대부분 아시다시피, Spring Data JPA는 exists 함수를 제공하지 않기 때문에, 이를 대체하고자 Querydsl를 사용합니다. 또한, Querydsl은 서브쿼리로만 exists 함수를 제공하고 성능상 이슈가 있어 직접 구현해야하는 걸로 알고 있습니다. 직접 얼만큼 성능차이가 있는지 눈으로 보기 위해서 몇가지 경우를 직접 성능 테스트 해보았습니다. Querydsl의 기본 ex.. 2023. 7. 4.
동시성 이슈와 데드락 문제를 비관적 락를 이용해 해결하다. 문제 상황 봉사 매칭 서비스 사이드 프로젝트에서 다중 사용자가 봉사 일정 신청시 동시성 이슈가 발생했다. 즉, 봉사 일정에 참가 가능한 인원이 한명이고, 3명의 신청자가 동시에 참가 신청을 했을 때 동시성 이슈로 인해 모두 참가되는 문제가 발생한 것이다. 개발 중인 서비스 DB의 일부분이다. 앞서 문제를 다시 설명하자면, 일정 테이블:일정 참가자 테이블=1:N 관계이고 사용자 3명이 동시 신청시 일정 참가자 테이블에 3개의 데이터가 모두 insert 되는 것이다. 간단히 테스트를 통해 실제 동시성 이슈가 발생하는지 보도록 하자. 위는 코드는 일정 참가 신청시 호출되는 Service 메서드이다. 간략히 설명하자면, 아래의 플로우로 일정 신청이 진행된다. 일정 검증(존재 여부, 참여 가능 일자 여부) 일정 .. 2023. 6. 28.
스프링의 예외 누수 문제 해결 변천사 초기 상황 앞서 글에서 말했다시피 예외 누수의 문제가 남아있다. Repository에 현재 JDBC 기술을 사용하고 있고 JDBC 예외인 SQLException는 체크 예외이기 때문에 처리하거나 던져야하며, 이로 인해 Service, Controller도 해당 예외를 적어야한다.(throws) 즉, Service, Controller가 특정 예외에 의존하게 되는 것이다. (참고로 체크 예외, 언체크 예외의 기본 개념을 안다는 전체하에 설명할 예정이다.!!) 체크 예외를 사용할 시 어떤 파급 효과가 발생할 수 있는지 살펴보자. 기본적으로 예외들의 대다수는 복구 불가능 예외이므로, Service, Controller에서는 예외를 던지게 되고 스프링 인터셉터, controllerAdvice, 서블릿 필터에서 .. 2023. 6. 25.