반응형

JAVA 151

[JPA] 프로젝트 동시성 이슈 해결을 위해 낙관적 락을 걸어보았다

롤링페이퍼 기반 서비스 플랫폼을 개발하던 중 아래 버그를 발견했다. ??? 대체 어떤 일이 일어난다는 거야... 하는 마음으로 같은 메시지를 막 광클했을 때 위와 같이 `에러가 발생했어요` 페이지가 뜨는 것을 발견했다. 해당 메시지에 좋아요를 광클하거나, 같은 계정으로 PC/모바일 등 다중 환경 접속 후 좋아요를 여러번 동시에 누르면 발생하는 버그였다. 즉, 동시성 이슈로 발생한 문제였다! 우리 서비스에서는 한 명의 회원이 같은 메시지에 좋아요를 2개 이상 누를 수 없다. 인스타나 페이스북처럼 좋아요가 눌러진 상태에서 좋아요를 또 누르면 좋아요 취소가 작동돼야 한다. 하지만 위와 같이 광클하는 경우에는 그 찰나에 같은 회원의 메시지 좋아요가 2개 들어가버린 것을 확인할 수 있었다. 상황을 그림으로 정리해..

[221021] 우아한테크코스 4기 최종 데모데이 후기

약 4달동안 진행했던 프로젝트를 우테코 인원 모두에게, 그리고 외부인들에게 공개되는 최종 데모데이가 10월 21일에 열렸다! 최근 공부할 게 많아서 (그리고 약간의 귀차니즘으로 인해) 이제서야 포스팅을 하게 된다. 간략하게 최종 데모데이의 분위기, 그리고 우리의 프로젝트를 소개해보도록 하겠다. 프로젝트 간단 소개 데모데이 분위기를 소개하기 전, 우리가 어떤 프로젝트를 개발하고 외부에 공개했는지 간단하게 소개해보도록 하겠다. 우리 팀이 개발하고 있는 프로젝트는 모임 기반 롤링페이퍼 서비스 플랫폼인 `내 마음을 편지로, 내 편` 이다. 소개페이지 링크는 아래와 같다. https://sites.google.com/woowahan.com/woowacourse-demo-4th/%ED%94%84%EB%A1%9C%E..

[Spring] REQUIRED, REQUIRES_NEW 옵션과 Try-Catch

스프링에서 트랜잭션을 다루다보면 두 개 이상의 트랜잭션이 서로 합류하는 경우가 존재한다. 이 때, @Transactional의 전파레벨을 적절히 조정하는 것이 중요하다. 스프링 전파레벨에 대한 이해가 부족하다면 아래 글을 읽고 오는 것을 추천한다. 스프링 @Transactional 전파레벨: https://kth990303.tistory.com/385 @Transactional REQUIRES_NEW 롤백 상황: https://kth990303.tistory.com/387 지난 포스팅(387번)에서는 REQUIRES_NEW 전파레벨 옵션일 때 @TransactionalEventListener를 이용하여 자식이 롤백되더라도 부모가 롤백되지 않도록 설정해주었다. 이번 포스팅에서는 try-catch에 대해 살..

[Spring] REQUIRES_NEW 옵션만으론 자식이 롤백될 때 부모도 롤백된다

두 개 이상의 트랜잭션이 합류할 경우, 트랜잭션 전파레벨 옵션 설정으로 트랜잭션을 관리할 수 있다. 특히, 트랜잭션 전파레벨 중 REQUIRED, REQUIRES_NEW는 실제로도 꽤나 자주 쓰이는 옵션이라 알아두면 더더욱 좋다. 전파레벨 옵션에 대해 궁금하다면 아래 글을 살펴보자. https://kth990303.tistory.com/385 [Spring] @Transactional의 전파 레벨에 대해 알아보자 스프링에선 진행중인 트랜잭션에서 다른 트랜잭션이 참여할 때의 합류조건을 설정할 수 있는 Propagation 옵션이 존재한다. DB에서 자체적으로 제공해주는 트랜잭션 격리레벨과 다르게 전파레벨은 kth990303.tistory.com 이번 포스팅에서는 REQUIRES_NEW 전파레벨 옵션에 대해..

[Spring] @Transactional의 전파 레벨에 대해 알아보자

스프링에선 진행중인 트랜잭션에서 다른 트랜잭션이 참여할 때의 합류조건을 설정할 수 있는 Propagation 옵션이 존재한다. DB에서 자체적으로 제공해주는 트랜잭션 격리레벨과 다르게 전파레벨은 스프링에서 개발자들의 편의를 위해 제공해주는 기능이다. 특히, 트랜잭션 격리 레벨과 마찬가지로 전파레벨은 cs 면접에서 자주 물어보는 주제이기도 하므로 잘 학습해두는 것이 좋을 듯하다. 이번 포스팅에선 트랜잭션 전파 레벨에 대해 작성해보도록 하겠다. 트랜잭션 전파 레벨은 총 7가지 트랜잭션 전파레벨에는 총 7가지 종류가 있다. 스프링 문서에 적혀있는 내용을 바탕으로 한 번 살펴보자. REQUIRED: Support a current transaction, create a new one if none exists...

[220930] DB 제3정규화 위반 문제점을 무시하고 프로젝트 연관관계 수정한 삽질 후기

프로젝트 엔티티 연관관계를 개선하는 과정을 진행하면서 여러 삽질을 했다. 약 5~6가지 삽질을 했는데, 이번 포스팅에선 그 중 하나인 4번째 삽질, DB 정규화 위반 문제점 중 하나인 갱신 이상을 무시하고 성능 및 가독성을 개선하려 한 후기에 대해 적어보려 한다. 삽질한 부분의 도메인 구조 회원이 모임(Team)에 가입할 때, 모임에서 사용할 닉네임을 지어 가입하게 된다. 이 때 TeamParticipation이 생성된다. TeamParticipation에는 모임에서 사용하는 닉네임이 들어있다. (즉, TeamParticipation은 Member와 Team의 중간테이블) 특정 모임(Team)은 여러 롤링페이퍼(Rollingpaper)를 소유할 수 있다. (1:N @ManyToOne 단방향) 특정 롤링페..

[220928] 우아한테크코스 레벨4 - MVC 구현하기 미션 후기

이전에 진행됐던 `톰캣 구현하기` 미션에 이어 `MVC 구현하기` 미션이 시작됐다. 여기에서 1번은 HandlerMapping, 2번은 HandlerAdapter이다. 이번 미션에서는 위를 구현해보고 리팩터링하여 컨트롤러가 어떻게 찾아와지는지, 해당 메서드를 어떻게 실행시키고 ModelAndView로 반환시키는지 확인해보는 미션이다. 환경은 JSP 파일을 렌더링한 응답을 보내줘야 하는 SSR 환경이라고 가정한다. 1단계 - @MVC 프레임워크 구현하기 요구사항 AnnotationHandlerMappingTest가 정상 동작한다. DispatcherServlet에서 HandlerMapping 인터페이스를 활용하여 AnnotationHandlerMapping과 ManualHandlerMapping 둘다 처리..

[QueryDSL] queryDSL 프로젝트 적용 후기 및 트러블슈팅

우테코 프로젝트에서는 Spring Data JPA를 사용하고 있었다. Spring Data JPA를 이용하면 인터페이스 생성 만으로도 SimpleJpaRepository에 내장된 다양한 CRUD 메서드를 활용할 수 있고, 추가로 커스텀 메서드도 편리하게 만들 수 있다는 장점이 존재한다. 그러나 Spring Data JPA는 동적 쿼리를 사용하기 어렵고 복잡한 쿼리는 @Query 어노테이션을 이용하여 JPQL을 직접 작성해주어야 한다는 문제점이 존재한다. 따라서 이번 기회에 queryDSL을 적용하여 컴파일 시점에 문법 오류를 잡아낼 수 있게 하고, 복잡한 쿼리를 리팩터링하는 데에 도전해보았다. 특히 위처럼 DTO를 반환하는 repository method의 경우 @Query로 작성하면 DTO 패키지명을 ..

[JPA] 벌크 Update, Delete 연산과 영속성 컨텍스트

벌크 수정연산과 벌크 삭제연산을 각각 수행한 후에 별도로 영속성 컨텍스트 초기화 작업을 하지 않았다고 가정하자. 이후에 전체조회 작업을 시행하면 update는 연산이 적용되지 않은 영속성 컨텍스트 데이터, delete는 연산이 적용된 DB 데이터 결과가 조회되는 것을 확인할 수 있다. 왜 그런 것일까? 이를 이해하기 위해선 영속성 컨텍스트를 제대로 이해하고 있어야 한다. 아래 예시와 함께 살펴보도록 하자. Update 벌크연산 상황 영속성 컨텍스트와 DB에 아래 데이터가 있다고 하자. 위 상황에서 아래와 같이 28살 미만은 이름을 전부 비회원으로 바꾸라는 bulk update 연산을 수행해보자. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Test public void bulkUpdate..

[220913] 우아한테크코스 레벨4 - 톰캣 구현하기 미션 후기

레벨4에 들어서면서 그동안 우리가 흔히 사용했던 스프링에 대해 좀 더 딥하게 알아보고 구현해보는 시간을 가지게 됐다. 아래는 우테코 레벨4 일정이다. 그 중에서 첫 번째 미션은 [톰캣 구현하기]이다. 그 동안 우리는 스프링을 이용한 덕분에 HTTP 요청을 받으면 그에 맞는 응답을 편리하게 만들어줄 수 있었다. 이는 Dispatcher Servlet이 있었기에 가능한 것. 이번 미션을 통해서 WAS, tomcat, Dispatcher Servlet이 각각 무엇인지, 어떠한 역할을 하는지 배울 수 있었다. 특히 4단계의 '동시성 확장하기' 미션 덕분에 스레드, 스레드풀에 대한 개념을 공부할 수 있었다. 내 최종 코드 및 각 단계별 PR은 아래 레포에서 확인할 수 있다. https://github.com/wo..

반응형