Skip to content

Conversation

Soundbar91
Copy link
Collaborator

@Soundbar91 Soundbar91 commented Oct 4, 2025

🔍 개요

Image
  • Spring Data 리파지토리 클래스를 탐색하는 과정(store assignment)에서 다음과 같은 로그 발생
  • 코인 프로젝트는 Repository를 상속받는 리파지토리 인터페이스를 사용하고 있음
    • Repository의 경우 최상단에 존재하는 인터페이스이고, 단지 Spring Data 스캔 후보임을 표시
    • 도메인 엔티티에 달린 어노테이션까지 확인해야 판별이 가능함
  • 리파지토리 스캔 범위 또한 별도로 설정되어 있지 않아, 모든 리파지토리를 탐색
    • store assignment 과정에서 다른 store의 인터페이스도 탐색
    • 다른 store의 인터페이스에서 판별 실패로 수 많은 로그 발생
    • 3번의 store assignment 과정에서 동일한 인터페이스르 3번 훝어보는 과정 발생 → 구동 시간 증가

🚀 주요 변경 내용

어노테이션 기반 필터링

@Configuration
@EnableJpaAuditing
@EnableJpaRepositories(
    basePackages = "in.koreatech.koin",
    includeFilters = @ComponentScan.Filter(
        type = FilterType.ANNOTATION,
        value = JpaRepository.class
    )
)
@Profile("!test")
public class JpaConfig {

}
  • 각 스토어의 리파지토리 설정 클래스에 @EnableXXRepositories 어노테이션을 추가
  • 해당 어노테이션의 옵션으로 커스텀 어노테이션 기반으로 필터링을 진행한다고 설정
  • 이후 관련 리파지토리 인터페이스 해당 어노테이션 설정

JPA 설정 파일 분리 및 bootstrapMode 설정

@Configuration
@EnableJpaRepositories(
    basePackages = "in.koreatech.koin.admin",
    bootstrapMode = LAZY
)
@Profile("!test")
public class AdminJpaConfig {

}

@Configuration
@EnableJpaRepositories(
    basePackages = "in.koreatech.koin.domain"
)
@Profile("!test")
public class DomainJpaConfig {

}


@Configuration
@EnableJpaAuditing
@Profile("!test")
public class JpaConfig {

}
  • domain과 admin의 JPA 설정 파일을 분리
  • admin의 경우 bootstrapMode를 LAZY으로 설정
    • 리파지토리 초기화 전략
    • DEFAULT : 리포지토리 초기화가 Spring 컨텍스트 시작 시점에 즉시 시작
    • LAZY : 리포지토리 초기화가 실제로 사용할 때까지 지연
    • DEFERRED : 리포지토리 초기화가 비동기로 진행

미사용 리파지토리 인터페이스 삭제

  • 미사용 리파지토리 인터페이스 리스트
    • CommentRepository
    • KoinArticleRepository
    • KoreatechArticleRepository
    • EventArticleImageRepository
    • MenuDetailRepository
    • MenuImageRepository
    • ReviewImageRepository
    • ReviewMenuRepository
    • ShopCategoryMapRepository
    • ShopImageRepository
    • ShopOpenRepository
    • AccessHistoryAbtestVariableRepository

테스트 환경 : MacBook Air 15 (M3, 16GB, macOS Sonoma)
각 테스트는 독립으로 진행

시나리오 JPA 스캔 Mongo 스캔 Redis 스캔 합계 Root WebApplicationContext: initialization
초기 상태 384ms 62ms 66ms 512ms 2289ms
어노테이션 기반 필터링 331ms 49ms 51ms 431ms 2629ms
미사용 리파지토리 인터페이스 삭제 363ms 56ms 62ms 481ms 2088ms
jpa 설정 파일 분리 및 bootstrapMode 설정 187ms(LAZY) + 165ms 56ms 62ms 470ms 2528ms
  • 어노테이션 기반 필터링 + JPA 설정 파일 분리 및 bootstrapMode 설정 + 미사용 리파지토리 인터페이스 삭제 적용
JPA 스캔 Mongo 스캔 Redis 스캔 합계 Root WebApplicationContext: initialization
185ms(LAZY) + 109ms 35ms 51ms 380ms 2433ms

💬 참고 사항

store assignment

  • 리파지토리 인터페이스가 어떤 store 전용인지 판별하는 과정

    store : Jpa, MongoDB, Redis 등 데이터 저장소 모듈

  • 판별 과정

    • 1차로 리파지토리 인터페이스가 상속 받고 있는 인터페이스로 판별
      • JpaRepository : JPA
      • MongoRepository : Mongo
      • KeyValueRepository : Redis
    • 2차로 도메인 엔티티 클래스에 달린 어노테이션으로 판별
    • 1차, 2차 모두 실패할 경우 사진과 같은 로그를 찍고 무시
  • 어노테이션 기반 필터링 커밋 : dfd7d30, c0fe762, 38545e5, cfe6757, e9efef3, 3fc227f, 4fe5e56

  • 미사용 리파지토리 인터페이스 삭제 커밋 : f3a6fe7

  • JPA 설정 파일 분리 및 bootstrapMode 설정 커밋 : 59347ad, 91c3901, a4204a9

  • 해당 커밋 위주로 봐주시면 될 거 같고, 리파지토리 어노테이션이 잘 걸려있는지 한 5번은 본거 같은데 요쪽은 한 번 훝어봐주시면 될 거 같습니다.


✅ Checklist (완료 조건)

  • 코드 스타일 가이드 준수
  • 테스트 코드 포함됨
  • Reviewers / Assignees / Labels 지정 완료
  • 보안 및 민감 정보 검증 (API 키, 환경 변수, 개인정보 등)

@github-actions github-actions bot added 공통 백엔드 공통으로 작업할 이슈입니다. 리팩터링 리팩터링을 위한 이슈입니다 labels Oct 4, 2025
Copy link

github-actions bot commented Oct 4, 2025

Unit Test Results

668 tests   667 ✔️  1m 18s ⏱️
164 suites      1 💤
164 files        0

Results for commit e63714e.

♻️ This comment has been updated with latest results.

@Soundbar91 Soundbar91 self-assigned this Oct 4, 2025
@Soundbar91 Soundbar91 marked this pull request as draft October 5, 2025 15:45
@Soundbar91 Soundbar91 marked this pull request as ready for review October 6, 2025 06:58
Copy link
Collaborator

@BaeJinho4028 BaeJinho4028 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

코멘트 몇가지만 확인해주세요. 👍

+)

  1. config 패키지를 global 패키지 밖으로 빼주시면 감사드리겠습니다.
  2. repository 어노테이션은 global 패키지 안에 따로 패키지를 만들어서 보관하면 좋을것 같습니다.
  3. repository 어노테이션의 이름이 스캔 용도라는게 명확했으면 좋겠습니다.
  4. 꼭 어노테이션을 붙여야만 스캔이 빨라지나요?
    (mongo랑 redis 리포지토리가 적은편이니 이 두개의 경우에만 어노테이션 넣고, 나머지는 그냥 jpa로 인식되게하는 것도 한번 고민해봐도 좋을 것 같습니다.)

import in.koreatech.koin.domain.order.address.model.RoadNameAddressDocument;

@Repository
@in.koreatech.koin.global.config.repository.MongoRepository
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기 import 가 필요해요

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RoadNameAddressRepository가 MongoRepository를 상속받고 있어서, 풀패스로 나오는 거 같습니다

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

어노테이션 네이밍 수정하면서 해결됐습니다.

@Profile("!test")
public class MongoConfig {

} No newline at end of file
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No newline at end of file

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 커밋에서 발생한 거 같습니다 !
928dd86 여기에서 수정했습니다

@Target(TYPE)
@Retention(RUNTIME)
public @interface MongoRepository {
} No newline at end of file
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No newline at end of file

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기도 동일합니다

Comment on lines 11 to 12
public @interface RedisRepository {
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

줄넘김 필요

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bd66e4b 수정했습니다

Comment on lines 11 to 12
public @interface MongoRepository {
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기도 줄넘김 필요

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

38b5a03 수정했습니다

Copy link
Collaborator Author

@Soundbar91 Soundbar91 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

config 패키지를 global 패키지 밖으로 빼주시면 감사드리겠습니다.

f05caa5 수정했습니다.

repository 어노테이션은 global 패키지 안에 따로 패키지를 만들어서 보관하면 좋을것 같습니다.

d2ad960 /global/marker으로 패키지를 만들어서 옮겼습니다.

repository 어노테이션의 이름이 스캔 용도라는게 명확했으면 좋겠습니다.

edf05e1, b7f660f, c26ffdb 에서 수정했습니다. 해당 작업을 할 때 marker라는 용어를 접해서 이를 반영했는데, 괜찮으실까요 ? 스캔 용도라는 약간 거리가 먼 거 같은데, 해당 인터페이스가 XXRepository임을 나타내는 데 괜찮다고 생각합니다.

꼭 어노테이션을 붙여야만 스캔이 빨라지나요? (mongo랑 redis 리포지토리가 적은편이니 이 두개의 경우에만 어노테이션 넣고, 나머지는 그냥 jpa로 인식되게하는 것도 한번 고민해봐도 좋을 것 같습니다.)

추가로 테스트를 진행했습니다.

시나리오 JPA 스캔 Mongo 스캔 Redis 스캔 합계 Root WebApplicationContext: initialization
어노테이션 기반 필터링 + JPA 설정 파일 분리 + bootstrapMode 설정 185ms(LAZY) + 109ms 35ms 51ms 380ms 2433ms
어노테이션 기반 필터링 (JPA, Mongo, Redis) 301ms 35ms 54ms 390ms 2250ms
JPA 어노테이션 삭제 (Mongo, Redis 유지) 381ms 37ms 55ms 473ms 2478ms
JPA 설정 파일 분리 및 bootstrapMode 설정 + JPA 어노테이션 삭제 (Mongo, Redis 유지) 233ms(LAZY) + 138ms 32ms 60ms 463ms 2436ms

어노테이션의 존재 여부에 따라 차이가 존재함은 확실한 거 같습니다.

다만, 재테스트 과정에서 JPA 설정 파일 분리 + bootstrapMode 설정을 제외하고어노테이션 기반 필터링만 적용했을 때 개선이 많이 됨을 확인했습니다.

b83e98c에서 다시 수정했습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
공통 백엔드 공통으로 작업할 이슈입니다. 리팩터링 리팩터링을 위한 이슈입니다
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[공통] Spring Data 스캔을 개선한다.
2 participants