Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: 쪽지 조회시 로깅을 위한 기능 비동기 처리 #584

Open
wants to merge 7 commits into
base: dev_backend
Choose a base branch
from

Conversation

chaewon121
Copy link
Collaborator

@chaewon121 chaewon121 commented Nov 20, 2023

📌 관련 이슈

🛠️ 작업 내용

  • 부기능 함수 비동기 처리 하기
  • 비동기 처리 하면서 발생하는 다양한 문제 해결

🎯 리뷰 포인트

비동기를 도입한 이유

저희 서비스에는 게임중 읽은 쪽지들을 게임이 끝난 후 보여주는 기능이 있습니다.

그래서 내부동작이

쪽지를 읽는다 → 읽은쪽지로그에 해당 쪽지가 있는지 검증한다 → 없으면 읽은쪽지로그 테이블에 저장한다 → 이로직이 끝난후 쪽지를 보여준다

이 순서로 동작이 일어납니다.

만약 읽은쪽지로그 테이블의 데이터가 많이 쌓인다면 사용자는 쪽지 하나를 읽기 위해서 읽은쪽지로그를 모두 찾고 저장하는 동작이 끝날때가지 요청을 기다려야합니다.

저는 쪽지를 읽는 행위를 하는 것은 그 행위만 하도록 하고 싶었습니다. 중복제거를 위해 쪽지가 있는지 확인하는 동작, 읽은쪽지로그 테이블에 저장하는 동작까지 쪽지를 읽는 행위에 포함되는것이 맞지 않다고 생각했습니다.

먼저 주기능과 부 기능을 분리하기 위해서 트렌젝션을 분리해야 한다고 생각했습니다.

부기능 함수에 *@Transactional*(propagation = Propagation.REQUIRES_NEW)

이 어노테이션을 달아주었습니다. 하지만 저 어노테이션만으로는 스레드 분리가 되지 않기때문에 부 기능에서 예외가 발생하면 주기능까지 전파되는것이 해결되지 않았고, 스레드가 분리되지 않는 이상 결국 부기능을 주기능이 기다려야 했습니다.

그래서 비동기로 스레드를 분리해야겠다고 생각했습니다.

비동기로 스레드를 분리하면 주기능과 부기능이 완전히 분리가 되었고 트렌젝션도 별도로 진행되었습니다.

비동기 여정

1. 비동기 처리를 위한 조건

  • private method는 사용 불가
  • self-invocation(자가 호출) 불가, 즉 inner method는 사용 불가

참고 블로그 : [https://velog.io/@gillog/Spring-Async-Annotation비동기-메소드-사용하기](https://velog.io/@gillog/Spring-Async-Annotation%EB%B9%84%EB%8F%99%EA%B8%B0-%EB%A9%94%EC%86%8C%EB%93%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0)

위 조건을 만족하기위해 LetterLogService 를 분리하게 되었습니다.

2. 비동기 예외처리

비동기 함수는 메인스레드의 작업이 아니기 때문에 ExceptionHandler 가 잡아주지 못하고, 따로 처리해아합니다. 그래서 AsyncExceptionHandler 를 구현하게 되었습니다.

하지만 handleUncaughtException 는 로그를 찍을 수는 있지만 클라이언트에게 예외를 보여주지는 못하는것 같습니다 (문제점이라고 생각..)

비동기 테스트 하기

비동기 함수를 테스트 하는것이 매우 까다로웠습니다. 이유는 테스트 함수도 하나의 스레드이기 때문에 비동기 함수가 비동기로 실행이 되면 비동기 함수가 끝나기전에 테스트가 끝나버리는 문제가 발생했습니다.

CountDownLatch, CompletableFuture 등 다양한 방법을 시도했으나 저희이 비동기 함수는 void였고 생각보다 많이 까다로워서 잘 해결되지 않았습니다.

결국 제가 해결한 방법은 비동기 함수가 실행되는 스레드를 빈으로 등록하고 빈 이름을 "asyncExecutor" 로 정해주었습니다.

@Configuration
public class AsyncConfig implements AsyncConfigurer {

    @Override
    @Bean(name = "asyncExecutor")
    public Executor getAsyncExecutor() {
        return new ThreadPoolTaskExecutor();
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new AsyncExceptionHandler();
    }
}

그리고 테스트 실행시 빈을 초기화 할때

@TestConfiguration
public class AsyncTestConfig {

    @Bean
    public AsyncExecutorPostProcessor asyncExecutorPostProcessor() {
        return new AsyncExecutorPostProcessor();
    }

    static class AsyncExecutorPostProcessor implements BeanPostProcessor {

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (beanName.equals("asyncExecutor")) {
                return new SyncTaskExecutor();
            }
            return bean;
        }
    }
}

"asyncExecutor" 라는 빈이 등록될 시 해당 빈을 동기로 실행하는 로직을 추가해주었습니다.

참고 블로그: [https://velog.io/@byeongju/비동기-로직-동기-방식으로-테스트하기](https://velog.io/@byeongju/%EB%B9%84%EB%8F%99%EA%B8%B0-%EB%A1%9C%EC%A7%81-%EB%8F%99%EA%B8%B0-%EB%B0%A9%EC%8B%9D%EC%9C%BC%EB%A1%9C-%ED%85%8C%EC%8A%A4%ED%8A%B8%ED%95%98%EA%B8%B0)

하지만 비동기 함수에서 발생하는 예외는 예외를 던지지않고 로그만 찍기 때문에 따로 테스트할 방안을 찾지 못하여서 해당 테스트는 일단 주석처리 해놓았습니다..

  • 리뷰 포인트

⏳ 작업 시간

추정 시간: 8시간
실제 시간: 48시간
비동기 처리할때 고려할 사항이 생각보다 너무 많았어서 산넘어 산이었네요..

@chaewon121 chaewon121 changed the title Refactor/#577 refactor: 쪽지 조회시 로깅을 위한 기능 비동기 처리 Nov 20, 2023
Copy link
Contributor

github-actions bot commented Nov 20, 2023

Unit Test Results

  35 files    35 suites   6s ⏱️
194 tests 194 ✔️ 0 💤 0
200 runs  200 ✔️ 0 💤 0

Results for commit 017a2c2.

♻️ This comment has been updated with latest results.

@chaewon121 chaewon121 added 🍀 백엔드 백엔드 라벨 D-2 labels Nov 20, 2023
@chaewon121 chaewon121 self-assigned this Nov 20, 2023
@dooboocookie
Copy link
Collaborator

내일 면접 보고와서 리뷰할게용...
이 내용 공부하느라 오늘은 리뷰를 못달았네요 ㅠㅠㅠ

@dooboocookie dooboocookie added D-0 and removed D-2 labels Dec 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
D-0 🍀 백엔드 백엔드 라벨
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants