inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

스프링부트로 직접 만들면서 배우는 대규모 시스템 설계 - 게시판

좋아요 수 구현

lockType 오류 및 카운트 체크 안 됨

해결된 질문

87

작성자 없음

작성한 질문수 0

0

안녕하세요! 강의 잘 듣고 있습니다. 좋은 강의 감사합니다.

실습하다가 오류가 생겨 문의 드립니다.

    void like(Long articleId, Long userId, String lockType) {

        restClient.post()
                .uri("/v1/article-likes/articles/{articleId}/users/{userId}/" + lockType, articleId, userId)
                .retrieve();
    }

    @Test
    void likePerformanceTest() throws InterruptedException {

        ExecutorService executorService = Executors.newFixedThreadPool(100); // 100개의 스레드 풀 생성
        // 각 lock type별로 테스트
        likePerformanceTest(executorService, 1111L, "pessimistic-lock-1");
        likePerformanceTest(executorService, 2222L, "pessimistic-lock-2");
        likePerformanceTest(executorService, 3333L, "optimistic-lock");
    }

    void likePerformanceTest(ExecutorService executorService, Long articleId, String lockType) throws InterruptedException {

        CountDownLatch latch = new CountDownLatch(3000);
        System.out.println(lockType = " start");

        like(articleId, 1L, lockType);

        long start = System.nanoTime();

        for (int i = 0; i < 3000; i++) {
            long userId = i + 2;
//            String finalLockType = lockType;
            executorService.submit(() -> {
                like(articleId, userId, lockType);
                latch.countDown();
            });
        }

        latch.await();
        long end = System.nanoTime();

        System.out.println("lockType = " + lockType + ", time = " + (end - start) / 1_000_000 + " ms");
        System.out.println(lockType + " end");

        Long count = restClient.get()
                .uri("/v1/article-likes/articles/{articleId}/count", articleId)
                .retrieve()
                .body(Long.class);

        System.out.println("count = " + count);
    }

여기서 '람다 식에 사용되는 변수는 final 또는 유사 final이어야 합니다' 라는 오류가 뜨더라고요.

// String finalLockType = lockType; 부분 주석 해제하고 람다 내부에 like(articleId, userId, finalLockType); 으로 하면

 

start

lockType = start, time = 914 ms

start end

count = 0

start

lockType = start, time = 589 ms

start end

count = 0

start

lockType = start, time = 567 ms

start end

count = 0

 

으로 출력도 잘 안 나옵니다.

 

애플리케이션 콘솔에는 아래 로고만 찍히고 나머지는 안 나옵니다.

Hibernate: select alc1_0.article_id,alc1_0.like_count,alc1_0.version from article_like_count alc1_0 where alc1_0.article_id=?

Hibernate: select alc1_0.article_id,alc1_0.like_count,alc1_0.version from article_like_count alc1_0 where alc1_0.article_id=?

Hibernate: select alc1_0.article_id,alc1_0.like_count,alc1_0.version from article_like_count alc1_0 where alc1_0.article_id=?

 

어느 부분이 문제일까요?

ArticleLikeController에서 count 경로는 테스트처럼 뒤에 /count 추가했습니다.

java mysql spring-boot kafka redis

답변 2

0

쿠케

안녕하세요!

 

위 내용만 보고는 원인 파악이 어렵네요, 혹시 스프링부트 버전이 강의와 다를까요?

최신 버전에서는 restClient에서 retrieve()까지만 하면 실제 api 호출이 안될 수 있어서, retrieve().toBodilessEntity()까지 호출해보시겠어요?

1

sally0109277

안녕하세요, 답변 감사합니다!

System.out.println(lockType + " start"); 인데 System.out.println(lockType = " start"); 으로 오타가 났었습니다 질문 올리고 발견했는데 이미 답변이 달려서 질문 삭제가 안 된다고 하더라고요...ㅎㅎ

강의 잘 듣고 있습니다 감사합니다!

0

인프런 AI 인턴

안녕하세요, 인프런 AI 인턴입니다. sally0109277님.

제시해주신 코드에서 나타난 문제를 해결하기 위한 몇 가지 접근 방법을 제시드리겠습니다.

1. ‘람다 식에 사용되는 변수는 final 또는 유사 final이어야 합니다’ 오류

람다식에서 외부 변수를 사용하려면 해당 변수는 final이거나, 사실상 final이어야 합니다. 이 오류는 실제로 발생할 수 있는데, lockType 변수를 람다 내에서 수정하지 않아야 합니다. 이미 시도하신 것처럼 finalLockType 으로 복사하여 사용하시면 잘 해결할 수 있습니다.

String finalLockType = lockType;
executorService.submit(() -> {
    like(articleId, userId, finalLockType);
    latch.countDown();
});

2. LOCK_TYPE 사용 문제

현재 오류의 원인 중 하나로 보이는 부분은 lockType 초기화 또는 호출 방식에 있다 할 수 있습니다. 특정 lockType을 사용하고 해당 부분이 서비스 로직에 영향을 미치는지를 먼저 분석할 필요가 있습니다.

  • lockType 변수의 정확한 사용 확인: like 메서드에서 전달된 마이크로서비스나 컨트롤러가 lockType을 제대로 수용하여 처리하고 반환 결과에 반영되었는지 확인합니다.

3. 로그 및 트랜잭션 검토

  • Hibernate 로그: 제공된 로그는 JPA를 사용하여 데이터 접근 시 발생하는 SQL을 보여줍니다. 여기서 count=0 이라는 결과는 데이터베이스에 올바른 insert가 이루어지지 않을 가능성이 있습니다. 트랜잭션이나 데이터베이스 연결에서의 문제를 확인할 필요가 있습니다.

  • 데이터베이스 상태: 테스트 환경에서 관련 데이터베이스 설정과 테스트 데이터가 적절하게 초기화되어 있는지 확인해야 합니다. 예를 들어, ArticleLikeCount와 관련된 데이터가 트랜잭션 내에서 올바르게 갱신되는지 점검하는 것이 필요합니다.

4. 테스트 전 결과 예측

  • 테스트 기대 결과: 테스트 전에 성공 사례와 예상 결과와 비교하여 모든 조건을 충족하고 있는지를 검증해야 합니다.

관련하여 유사한 문제를 해결하는데 도움이 되는 링크를 제공해드립니다:
- Java Lambda Expressions and Variable Capture

저는 질문자님의 이해를 돕고자 유사한 해결 방법을 안내드리고 있습니다. 현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드리며, 추가적으로 궁금한 사항이나 다른 문제가 있다면 계속해서 질문 주세요. 곧 지식공유자께서 추가적인 답변을 제공해 주실 것입니다. 🙏

@Version 어노테이션이 붙은 필드는 낙관적 락이든 비관적 락이든 업데이트가 됩니다.

0

29

1

consumer에서 에러가 발생할 경우 데이터 유실 문의

0

47

2

게시글 테스트 데이터 삽입

0

49

2

정렬, 필터, 검색 등의 조건이 붙을 경우 최적화할 수 있는 방법이 무엇이 있을까요?

0

102

2

좋아요 기능 정합성 보장 방법

0

96

2

좋아요 동시성처리 최적의 선택?

1

133

2

프론트엔드 msa 환경 api 주소 통합? 과 서버끼리 통신 방식에대해

0

91

2

안녕하세요 무한스크롤 강의듣다가 질문이 있습니다.

0

58

1

조회수 조회 로직 질문

1

67

2

비로그인 유저도 어뷰징 방지 정책

1

72

2

CommentServiceTest의 테스트 로직 질문

0

54

2

무한 스크롤 방식에서 페이지 번호 방식 쿼리의 문제점 의문

1

73

2

path 쿼리 관련 질문드립니다!

0

59

2

antigravity 에디터를 쓰신다면 종료해주세요

1

123

0

프로젝트 구조

0

88

2

article_like_count api test

0

77

2

이벤트 페이로드 객체의 생성 방식이 팩토리 메서드 패턴이 아닌 빌더 패턴인 이유가 궁금합니다!.

0

104

2

[33. 좋아요 수 구현] 에서 테스트 하는 화면 동시성 문제

0

90

2

findByPath에서 articleId로도 검색을 해야 할 것 같아요.

0

91

3

jpa ddl-auto none을 하는 이유와 join 방법

0

97

2

팩터리 메소드와 response 객체 사용 이유가 궁금합니다!

0

90

2

커서 기반 페이지네이션 과 무한 스크롤링

0

109

2

게시글 생성 로직에서 오류 발생시 redis 게시글 수 되돌리기

0

97

2

멀티 모듈이 아닌 MSA 환경에서 common

0

155

2