[Project] 5

[이슈 #5] Spring Life Cycle Event를 이용한 런타임에러를 컴파일 시점으로 변경하기

현 프로젝트에서 분산락을 적용하는 방법은 MySQL의 USER_LEVEL_LOCK, 즉 NAMED_LOCK 방식입니다. NAMED_LOCK은 get_lock() 함수를 이용해 임의의 문자열에 대해 잠금을 거는 방식으로 동작합니다. 따라서 임의의 문자열인 LockName이 반드시 지정되어야 합니다. 분산락 AOP를 사용하는 요청이 발생할 때마다, 분산락 Advice에서 파라미터에 @LockName 애노테이션이 존재하는지 검사하며, 해당 파라미터가 존재하지 않으면 다음 그림과 같이 런타임예외를 던지는 구조로 동작합니다. 위처럼 LockName애노테이션의 부재로 인해 예외를 던지는 것은 사용자의 잘못된 요청이 아닌 개발자의 실수가 원인입니다. 또한, 예외 처리 과정에서 별도의 핸들링 로직 없이 사용자에게 5X..

[Project]/[Momo] 2022.08.05

[이슈 #4] 분산락을 활용한 중복 데이터 삽입 이슈 해결3

분산락 중첩 적용 특정 사용자 요청을 처리하는 경우 분산락에 대한 중첩 적용이 필요했습니다. 모임을 생성하는 경우로 예시를 들어보겠습니다. 모임을 생성하는 요청은 우선, 회원에 대한 분산락을 획득하여 한 회원이 모임 생성 제한 갯수를 초과하여 생성하는 것을 검사합니다. 그 후, 모임이름에 대한 분산락을 획득하여 동일한 이름의 모임이 생성되는 것을 검사한 후 모임을 생성합니다. 따라서 다음과 같이 메서드를 분리하여 각 메서드에 별도의 분산락 적용을 위한 AOP를 적용했습니다. 컨트롤러 @Service @RequiredArgsConstructor public class ClubService { @DistributedLock(prefix = DistributedLockPrefix.MEMBER_ID) publi..

[Project]/[Momo] 2022.08.02

[이슈 #3] 분산락을 활용한 중복 데이터 삽입 이슈 해결2

이전 이슈를 통해 동시 요청시 중복 데이터 삽입 문제를 해결할 수 있었습니다. 그러나 아직 몇 가지 개선해야 할 점이 남아있습니다. 하드코딩된 lockname 파라미터 메서드 분리와 추상화 하드코딩된 lockname 파라미터 개선 현재 작성된 분산락 어드바이저는 다음과 같은 방식으로 lockname을 가져옵니다. String lockName = joinPoint.getArgs()[0].toString(); 위 방식은 분산락 AOP를 사용하는 경우 항상 첫번째 파라미터를 lockname 파라미터로 고정시키는 방식입니다. 하드코딩은 의미를 파악하기 어려우며 유지보수가 어렵다는 단점이 있으므로 분명히 개선해야할 문제입니다. 따라서 기존에 선언한 @DistributedLock 적용한 DistributedLock..

[Project]/[Momo] 2022.08.02

[이슈 #2] 분산락을 활용한 중복 데이터 삽입 이슈 해결1

문제인식 개발 중 클라이언트로부터 동일한 데이터에 대한 삽입 요청이 동시에 들어오는 경우, 중복 데이터 검사 로직을 거치더라도 데이터가 중복 삽입되는 문제를 발견했습니다. 회원이 모임을 가입할 때 발생하는 문제를 예시로 들어보겠습니다. 위와 같은 로직을 거쳐 회원이 모임에 가입하는 경우입니다. 위처럼 클라이언트의 오류로 동일한 두 요청이 동시에 들어온 경우 회원이 한 모임에 중복으로 가입하게 되는 문제가 발생하게 됩니다. 이 문제는 간단하게 Unique 제약조건을 통해 해결할 수 있습니다. 그러나 만약 '모임에 역할을 부여하여 관리자 회원은 관리자 역할과 일반 역할로 중복 가입할 수 있다.'라는 요구사항이 추가되면 다음과 같이 DB의 제약조건을 변경해 주어야 합니다. 또한, 제약조건을 변경하는 불편함을 ..

[Project]/[Momo] 2022.08.02

[이슈 #1] Spring Transaction의 Self Invocation 이슈

Spring Transaction의 Self Invocation 이슈 문제 인식 Spring Security를 이용한 OAuth 로그인 기능을 구현하기 위해 커스텀한 OAuth2UserService를 개발하던 중, 영속 상태에 있는 인스턴스의 필드 변경 사항이 DB에 저장되지 않는 문제를 발견하였습니다. 로그를 출력하며 확인해본 결과, 영속성 컨텍스트의 스냅샷을 이용한 변경 감지(dirty checking)뿐만 아니라 트랜잭션을 지원하는 쓰기 지연도 정상적으로 동작하지 않았습니다. 문제가 발생한 코드는 다음과 같습니다. @Service @RequiredArgsConstructor public class OAuth2UserServiceImpl implements OAuth2UserService { priv..

[Project]/[Momo] 2022.03.04