Skip to content
Closed

Main #288

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
344 commits
Select commit Hold shift + click to select a range
1bc7e84
[HSC-64] feat: MemberCoupon(회원 보유 쿠폰) 엔티티 구현
YeongHyeonHeo Feb 15, 2026
1d34a7c
[HSC-64] feat: Flyway 전용 계정 추가(.env파일)
YeongHyeonHeo Feb 15, 2026
83c4ce4
[HSC-64] feat: jpa ddl-auto: validate, flyway enabled: true로 수정
YeongHyeonHeo Feb 15, 2026
f4d3f65
[HSC-65] feat: Assembler 분리
rettooo Feb 15, 2026
86194b6
[HSC-65] feat: component 제거와 Config 등록
rettooo Feb 15, 2026
f1fd668
[HSC-65] feat: 카멜식 변경
rettooo Feb 15, 2026
a72293e
[HSC-65] feat: controller에 assembler 추가
rettooo Feb 15, 2026
07ba448
[HSC-64] feat: node_modules를 git 추적 대상에서 제외
YeongHyeonHeo Feb 15, 2026
0f0b611
[HSC-64] feat: Iptv 엔티티 plan_title 불필요한 공백 제거
YeongHyeonHeo Feb 15, 2026
ef7608f
[HSC-64] feat: V1__init.sql TIMESTAMP 수정
YeongHyeonHeo Feb 15, 2026
e70c26e
Merge pull request #15 from one-year-gap/feat/HSC-65
rettooo Feb 15, 2026
40b2dae
[HSC-64] feat: saled_price -> sale_pirce로 컬럼명 수정
YeongHyeonHeo Feb 15, 2026
35d62b0
Merge remote-tracking branch 'origin/dev' into feat/HSC-64
YeongHyeonHeo Feb 15, 2026
d5bc0dc
[HSC-64] feat: Enum import 경로 수정
YeongHyeonHeo Feb 15, 2026
a6a0f51
[HSC-64] feat: DTO 파일의 Enum import 경로 수정
YeongHyeonHeo Feb 15, 2026
b6cac79
[HSC-64] feat: 상품 관련 빌드 에러 수정
YeongHyeonHeo Feb 15, 2026
c7b6c20
[HSC-64] feat: 상품 관련 빌드 에러 수정
YeongHyeonHeo Feb 15, 2026
54c62e7
[HSC-64] feat: 상품 관련 테스트 코드 import 경로 수정
YeongHyeonHeo Feb 15, 2026
249ad96
[HSC-64] feat: MokitoBean 수정
YeongHyeonHeo Feb 15, 2026
8340961
[HSC-64] feat: HolliverseApplicationTests 파일 삭제
YeongHyeonHeo Feb 15, 2026
2bece5e
[HSC-64] feat: .env 파일 DB_USER_MIGRATOR 대신 FLYWAY_USER 사용
YeongHyeonHeo Feb 15, 2026
3c3398b
[HSC-64] feat: DB_USER_MIGRATOR 제거
YeongHyeonHeo Feb 15, 2026
ddd87f5
[HSC-64] feat: UsageMonthly 엔티티 yyyymm 필드 YearMonth 타입으로 변경
YeongHyeonHeo Feb 15, 2026
921fad5
[HSC-64] feat: UsageMonthly 엔티티 usageDetails 필드 초기화 적용(NPE 방지)
YeongHyeonHeo Feb 15, 2026
aa370d5
Merge pull request #16 from one-year-gap/feat/HSC-64
YeongHyeonHeo Feb 15, 2026
90f59af
[HSC-79] feat: 테스트 커버리지 제외 파일
rettooo Feb 16, 2026
d6c4b64
[HSC-79] feat: 테스트 커버리지 추가
rettooo Feb 16, 2026
9bc90ef
[HSC-79] feat: 상세 조회 use case Test코드
rettooo Feb 16, 2026
cd8e33f
[HSC-79] feat: 조회 controller 테스트 코드
rettooo Feb 16, 2026
dea382e
[HSC-80] feat: V2__create_refresh_token_table.sql 작성
YeongHyeonHeo Feb 16, 2026
f867be9
[HSC-80] feat: RefreshToken 엔티티 추가
YeongHyeonHeo Feb 16, 2026
511e22e
[HSC-84] style: husky hook update
tkv00 Feb 16, 2026
e18413a
Merge pull request #26 from one-year-gap/style/HSC-84
tkv00 Feb 16, 2026
49c4f73
[HSC-121] fix: 커버리지 변경
rettooo Feb 16, 2026
8f48737
Merge pull request #22 from one-year-gap/feat/HSC-79
rettooo Feb 16, 2026
9d9a904
Merge branch 'dev' into feat/HSC-80
YeongHyeonHeo Feb 16, 2026
c3c0dd7
[HSC-82] feat: 요금제 비교- application dto
rettooo Feb 16, 2026
ece1428
[HSC-82] feat: web dto
rettooo Feb 16, 2026
f957f07
[HSC-82] feat: 요금제 변경 로직(5G/LTE)
rettooo Feb 16, 2026
ae1c55d
[HSC-82] feat: 요금제 비교 usecase
rettooo Feb 16, 2026
4ff8cfd
[HSC-82] feat: Mapper, Assembler, Config
rettooo Feb 16, 2026
c3a9750
[HSC-82] feat: GET/api/v1/plans/compare 엔드포인트 추가
rettooo Feb 16, 2026
678373c
[HSC-82] test: 요금제 비교 테스트 데이터와 테스트
rettooo Feb 16, 2026
a8a3072
[HSC-82] test: /api/v1/plans/compare api테스트
rettooo Feb 16, 2026
3c02ce2
[HSC-82] chore: 파일 디렉토리 이동, CompareResponseMapper 분리
rettooo Feb 16, 2026
8e39a29
[HSC-82] chore: 파일 디렉토리 개선
rettooo Feb 16, 2026
36d806d
Merge pull request #24 from one-year-gap/feat/HSC-80
tkv00 Feb 16, 2026
04e06b7
[HSC-82] refactor: 확장 가능성 (모바일 요금제 제외)
rettooo Feb 16, 2026
c8d143d
[HSC-74] feat: 상품 정적데이터 적재(V3__insert_product_data.sql 작성)
YeongHyeonHeo Feb 16, 2026
555bde6
[HSC-82] test: 비교 UseCase Test코드
rettooo Feb 16, 2026
43d17ef
[HSC-74] refactor: PostgreSQL ENUM 매핑 최적화(@JdbcTypeCode 적용)
YeongHyeonHeo Feb 16, 2026
ae35515
[HSC-74] refactor: V3 상품 데이터 적재 Bulk Insert 방식으로 개선
YeongHyeonHeo Feb 16, 2026
8c87181
Merge pull request #28 from one-year-gap/feat/HSC-74
YeongHyeonHeo Feb 16, 2026
03b1d00
[HSC-39] feat: 로그인 리프레시 토큰부분까지 완료
bon0512 Feb 14, 2026
6647bbb
[HSC-39] feat: 전역 예외 추가
bon0512 Feb 14, 2026
cc84850
[HSC-39] feat: refresh 기능 추가
bon0512 Feb 15, 2026
4f3ab5a
[HSC-39] feat: member, address 엔티티 수정 , testcode 작성
bon0512 Feb 16, 2026
f0104fb
[HSC-39] feat: 테스트코드 수정
bon0512 Feb 16, 2026
04ead63
[HSC-39] test: RefreshToken 레포지토리 테스트 코드 작성
bon0512 Feb 16, 2026
a38aa40
[HSC-39] feat: ignore 파일 내용 추가
bon0512 Feb 16, 2026
3709446
[HSC-39] chore: gradle 수정
bon0512 Feb 16, 2026
4123715
[HSC-39] refactor: dto 클래스 dto 이름 추가
bon0512 Feb 16, 2026
a841864
[HSC-39] refactor: dto 클래스 이름 수정
bon0512 Feb 16, 2026
e6a6c20
[HSC-39] refactor: member엔티티 수정
bon0512 Feb 16, 2026
3ee7f75
[HSC-39] refactor: api 경로 수정
bon0512 Feb 17, 2026
aa01bdb
[HSC-39] refactor: api 다시 수정
bon0512 Feb 17, 2026
792aad2
[HSC-39] refactor: error코드 작성
bon0512 Feb 17, 2026
feb3f3c
Merge pull request #29 from one-year-gap/feat/HSC-39
bon0512 Feb 17, 2026
f047c69
[HSC-82] refactor: controller Test Mapper 의존 없이 수정
rettooo Feb 18, 2026
572b15f
[HSC-82] refactor: Controller가 compare 연산 수행
rettooo Feb 18, 2026
dcc0461
[HSC-82] chore: 필요 없는 파일 삭제
rettooo Feb 18, 2026
a58779c
[HSC-82] refactor: 상수값 매칭
rettooo Feb 18, 2026
6993c69
Merge branch 'dev' into feat/HSC-82
rettooo Feb 18, 2026
ece8dd2
[HSC-82] test: test 필터 제외 오류 수정
rettooo Feb 18, 2026
24ca0ed
Merge pull request #27 from one-year-gap/feat/HSC-82
rettooo Feb 18, 2026
4202b35
[HSC-101] fix: JWT 토큰 필터 제외
rettooo Feb 18, 2026
62ef9f0
Merge pull request #32 from one-year-gap/feat/HSC-101
rettooo Feb 18, 2026
b18a940
[HSC-103] feat: subscription Repo에서 구독 조회
rettooo Feb 18, 2026
9f43b07
[HSC-103] feat: subscription 엔티티 수정
rettooo Feb 18, 2026
aef8ba9
[HSC-103] feat: 요금제 변경 result record
rettooo Feb 18, 2026
bce4573
[HSC-103] refactor: repo 조회는 policy 폴더
rettooo Feb 18, 2026
84e3f36
[HSC-103] feat: ChangeProductRequest record
rettooo Feb 18, 2026
50dcf33
[HSC-103] chore: 파일 디렉토리 구조 변경
rettooo Feb 18, 2026
a4be3af
[HSC-103] feat: ChangeProductResponse 응답 구조
rettooo Feb 18, 2026
e835662
[HSC-103] feat: 요금제 변경 assember
rettooo Feb 18, 2026
c2a9ec4
[HSC-103] feat: 구독 Controller (구독 변경 / 신규 가입)
rettooo Feb 18, 2026
dd37cc6
[HSC-103] fix: policy에는 비즈니스 규칙만 담당
rettooo Feb 18, 2026
5de5c57
[HSC-103] test: 요금제 변경 policy 검증
rettooo Feb 18, 2026
30c65cf
[HSC-103] test: Usecase 검증 - 새로운 구독 저장
rettooo Feb 18, 2026
9cb6a50
[HSC-103] test: controller 테스트
rettooo Feb 18, 2026
e5b3f38
[HSC-103] fix: Assembler Component스캔
rettooo Feb 18, 2026
5cdecf9
[HSC-98] feat: 구글로그인 구현
bon0512 Feb 18, 2026
ac9a65a
[HSC-98] feat: 구글 로그인 구현
bon0512 Feb 18, 2026
d1c9bad
[HSC-103] refactor: subscription 엔티티에 deactivate / create 시각 파라미터 추가
rettooo Feb 18, 2026
4e0e26c
[HSC-103] refactor: 구독 변경 정책(비활성화/ 추가) 도메인 모델로 분리
rettooo Feb 18, 2026
d83e4c7
[HSC-103] refactor: UseCase에서 policy 결정 기반으로 엔티티 조작
rettooo Feb 18, 2026
858a57a
[HSC-103] test: 정책 테스트 decide 기준으로 수정
rettooo Feb 18, 2026
f8cc9fa
[HSC-103] chore: Clock 주입으로 구독 해지, 생성 시각 일관화
rettooo Feb 18, 2026
07176c3
[HSC-98] chore: merge origin/dev into feat/HSC-98
bon0512 Feb 18, 2026
eb1c5c0
[HSC-98] fix: resolve socialSuccessHandler
bon0512 Feb 18, 2026
3563c57
[HSC-98] fix: productControllerTest oauth 부분 통과되도록 설정
bon0512 Feb 18, 2026
5917009
[HSC-104] feat: application.yml 암호화 키 및 알고리즘 설정 추가
YeongHyeonHeo Feb 18, 2026
172b88a
[HSC-98] fix: 소셜로그인성공핸들러, 로그인성공핸들러, 공통로직 분리
bon0512 Feb 18, 2026
215bb6c
[HSC-104] feat: EncryptionTool, DecriptionTool 구현(암호화/복호화)
YeongHyeonHeo Feb 18, 2026
3eca9b8
[HSC-104] feat: CryptoConfig를 통해 암/복호화 도구 Bean 등록
YeongHyeonHeo Feb 18, 2026
af32877
[HSC-98] fix: DefaultOAuth2UserService DI 의존성 주입 원칙 준수
bon0512 Feb 18, 2026
eca7599
[HSC-104] refactor: 회원가입 시 이름 및 휴대폰번호 AES-256 암호화 적용
YeongHyeonHeo Feb 18, 2026
c55e44e
Merge pull request #37 from one-year-gap/feat/HSC-98
bon0512 Feb 18, 2026
5f2945c
[HSC-103] fix: test oauth 제외
rettooo Feb 18, 2026
2f95b04
[HSC-104] feat: 회원 목록 조회 요청 DTO 생성
YeongHyeonHeo Feb 18, 2026
8e16f5e
Merge pull request #36 from one-year-gap/feat/HSC-103
rettooo Feb 18, 2026
b2b00ea
[HSC-104] refactor: 회원가입 암호화 테스트 추가
YeongHyeonHeo Feb 18, 2026
ff830bd
[HSC-105] feat: 목록 조회 repo에 인기 상품 query 추가
rettooo Feb 18, 2026
52dbf3f
[HSC-105] feat: bestProduct list 파라미터 추가
rettooo Feb 18, 2026
43034d8
[HSC-105] feat: usecase에 N이 양수일때 bestCount만큼 가져오기
rettooo Feb 18, 2026
b0cd651
[HSC-105] feat: 응답 파라미터 boolean 값으로 추가
rettooo Feb 18, 2026
0c98007
[HSC-105] feat: Mapper/Assembler 에 추가
rettooo Feb 18, 2026
ecf0fab
[HSC-105] feat: Controller 파라미터 추가
rettooo Feb 18, 2026
5e84065
[HSC-105] test: 인기 상품 로직 테스트
rettooo Feb 18, 2026
2710ebe
[HSC-105] test: controller 테스트 추가
rettooo Feb 18, 2026
2bead2e
[HSC-105] fix: page 추가와 List -> Set
rettooo Feb 18, 2026
077737d
[HSC-104] chore: jOOQ 코드 생성을 위한 Gradle 설정 추가
YeongHyeonHeo Feb 18, 2026
d1c2e58
[HSC-104] feat: 회원 목록 조회용 DTO 및 MemberRawData 클래스 구현
YeongHyeonHeo Feb 18, 2026
a3c96ed
[HSC-104] feat: jOOQ 기반 회원 목록 검색 및 페이징 DAO 구현
YeongHyeonHeo Feb 18, 2026
ff1076d
[HSC-121] chore: sync issue template from infra
tkv00 Feb 18, 2026
9bd1d7f
[HSC-121] chore: sync PR template (default) from infra
tkv00 Feb 18, 2026
434ce1a
[HSC-121] chore: sync PR template (default) from infra
tkv00 Feb 18, 2026
4b9f6ff
[HSC-121] chore: sync PR template (deploy) from infra
tkv00 Feb 18, 2026
d5b7e0e
[HSC-121] chore: sync issue template from infra
tkv00 Feb 18, 2026
845b9ee
[HSC-121] chore: sync PR template (default) from infra
tkv00 Feb 18, 2026
e1b33c1
[HSC-121] chore: sync PR template (default) from infra
tkv00 Feb 18, 2026
45141ec
[HSC-121] chore: sync PR template (deploy) from infra
tkv00 Feb 18, 2026
f845589
[HSC-104] test: AdminMemberDao 페이징/검색 테스트
YeongHyeonHeo Feb 18, 2026
8875e7a
[HSC-104] feat: 암/복호화 유틸리티(EncryptionTool, DecryptionTool) 단위 테스트
YeongHyeonHeo Feb 18, 2026
7e461f7
[HSC-104] feat: 관리자 회원 목록 조회용 Response DTO 구현
YeongHyeonHeo Feb 18, 2026
b131ca1
[HSC-104] feat: AdminMemberAssembler 구현(복호화/마스킹 로직 추가)
YeongHyeonHeo Feb 18, 2026
1b03fd8
[HSC-104] test: AdminMemberAssembler 단위 테스트
YeongHyeonHeo Feb 18, 2026
7609a2c
[HSC-104] feat: RetrieveMemberUseCase 구현(회원 목록 조회 비즈니스 로직)
YeongHyeonHeo Feb 18, 2026
d2f3fcb
[HSC-104] test: RetrieveMemberUseCase 수정 및 단위 테스트
YeongHyeonHeo Feb 18, 2026
362846e
[HSC-104] feat: AdminMemberController 구현
YeongHyeonHeo Feb 18, 2026
a934a0a
[HSC-104] refactor: UseCase, DAO에 @Profile(admin) 추가
YeongHyeonHeo Feb 18, 2026
4ae9de5
[HSC-104] test: AdminMemberController 테스트 작성
YeongHyeonHeo Feb 18, 2026
c2ab34b
[HSC-104] feat: jooq 생성 코드를 Git 관리 대상으로 변경 및 CI 빌드 설정
YeongHyeonHeo Feb 18, 2026
22ead28
[HSC-104] fix: 빌드 에러
YeongHyeonHeo Feb 18, 2026
752d9c7
[HSC-104] chore: sourceSets 위치 변경
YeongHyeonHeo Feb 18, 2026
c3356ce
[HSC-104] fix: 빌드 에러
YeongHyeonHeo Feb 18, 2026
bf2b8e6
[HSC-104] fix: CI 컴파일 에러 해결
YeongHyeonHeo Feb 19, 2026
db54669
Merge branch 'dev' of https://github.com/one-year-gap/api-server into…
YeongHyeonHeo Feb 19, 2026
740d188
[HSC-105] fix: customer profile 추가
rettooo Feb 19, 2026
1a89758
Merge pull request #40 from one-year-gap/feat/HSC-105
rettooo Feb 19, 2026
c90bb67
Merge branch 'dev' of https://github.com/one-year-gap/api-server into…
YeongHyeonHeo Feb 19, 2026
0a7ae1e
[HSC-104] refactor: test코드 profile 추가
YeongHyeonHeo Feb 19, 2026
f50a8af
[HSC-104] feat: 관리자 계정 DB 권한 설정 마이그레이션 추가(V5)
YeongHyeonHeo Feb 19, 2026
9d2169a
[HSC-104] feat: @ActiveProfiles(admin) 추가
YeongHyeonHeo Feb 19, 2026
89a49e4
[HSC-104] fix: CI 에러 수정
YeongHyeonHeo Feb 19, 2026
ce85cba
[HSC-104] fix: DAO 테스트 비활성화
YeongHyeonHeo Feb 19, 2026
89d87d1
[HSC-104] fix: RequestMapping 수정
YeongHyeonHeo Feb 19, 2026
361b703
[HSC-104] fix: 연령대 필터링 LocalDate 루프 밖으로 이동
YeongHyeonHeo Feb 19, 2026
3f32674
[HSC-104] fix: AdminMemberDto -> record로 수정
YeongHyeonHeo Feb 19, 2026
900cb3b
[HSC-104] fix: AdminMemberListResponseDto -> record로 수정
YeongHyeonHeo Feb 19, 2026
dbc8fe4
[HSC-104] refactor: 암호화/복호화 유틸리티 예외 처리 구체화
YeongHyeonHeo Feb 19, 2026
721498e
[HSC-104] fix: 하드코딩된 암호화 키 제거 및 환경변수 설정
YeongHyeonHeo Feb 19, 2026
ca71d18
[HSC-104] refactor: 환경변수 관리 체계 개선 (.env 기반 주입)
YeongHyeonHeo Feb 19, 2026
2c76907
[HSC-104] test: JaCoCo 테스트 커버리지 제외 항목 추가(jooq 생성 코드)
YeongHyeonHeo Feb 19, 2026
846bd61
[HSC-104] feat: jooq 테이블
YeongHyeonHeo Feb 19, 2026
276c70b
Merge pull request #41 from one-year-gap/feat/HSC-104
bon0512 Feb 19, 2026
2d2c64c
[HSC-111] build: ECS build용 Dockerfile 생성
tkv00 Feb 19, 2026
cfeb89a
[HSC-111] fix: test용 REST API URL 수정
tkv00 Feb 19, 2026
9566079
Merge pull request #44 from one-year-gap/build/HSC-111
tkv00 Feb 19, 2026
2afab17
[HSC-111] deploy: ECS 배포 워크플로우 파일 추가
tkv00 Feb 19, 2026
b92fbb7
[HSC-121] fix: pr-verification 수정
tkv00 Feb 19, 2026
efc7045
Merge pull request #46 from one-year-gap/release/HSC-121
tkv00 Feb 19, 2026
7cf6f82
Merge branch 'main' into release/HSC-128
tkv00 Feb 21, 2026
37e7be6
Merge pull request #55 from one-year-gap/release/HSC-128
tkv00 Feb 21, 2026
bfadb98
Merge pull request #60 from one-year-gap/release/HSC-133
tkv00 Feb 21, 2026
5b9eabb
[HSC-134] fix: bootstrap 삭제 후 application.yaml으로 수정
tkv00 Feb 21, 2026
0bcfb65
[HSC-134] fix: spring cloud 환경 설정 위치 변경
tkv00 Feb 21, 2026
280d4a5
Merge pull request #62 from one-year-gap/release/HSC-134
tkv00 Feb 21, 2026
d4f36eb
Merge pull request #68 from one-year-gap/release/HSC-137
tkv00 Feb 22, 2026
88b0175
Merge pull request #77 from one-year-gap/release/HSC-149
tkv00 Feb 24, 2026
b6c7b35
Merge pull request #92 from one-year-gap/release/HSC-159
tkv00 Feb 27, 2026
3126e78
Merge pull request #111 from one-year-gap/release/HSC-181
tkv00 Mar 3, 2026
c0ae2a7
Merge pull request #121 from one-year-gap/release/HSC-190
tkv00 Mar 4, 2026
373d85f
Merge pull request #126 from one-year-gap/release/HSC-192
tkv00 Mar 4, 2026
4a87458
Merge pull request #144 from one-year-gap/release/HSC-222
tkv00 Mar 6, 2026
4130372
Merge pull request #158 from one-year-gap/release/HSC-236
tkv00 Mar 9, 2026
baa8ae7
Merge pull request #169 from one-year-gap/release/HSC-248
tkv00 Mar 9, 2026
5bb20c7
Merge pull request #174 from one-year-gap/release/HSC-260
tkv00 Mar 10, 2026
720e068
Merge pull request #182 from one-year-gap/release/HSC-270
tkv00 Mar 10, 2026
5ab7102
Merge pull request #187 from one-year-gap/release/HSC-274
tkv00 Mar 11, 2026
0479e26
Merge pull request #196 from one-year-gap/release/HSC-287
tkv00 Mar 12, 2026
f50caa8
Merge pull request #209 from one-year-gap/release/HSC-309
tkv00 Mar 15, 2026
6e2852e
Merge pull request #226 from one-year-gap/dev
tkv00 Mar 16, 2026
5fe1594
Merge pull request #234 from one-year-gap/release/HSC-343
tkv00 Mar 17, 2026
5500fe4
hotfix: application log 설정 off
tkv00 Mar 18, 2026
2b1f2b3
Merge pull request #236 from one-year-gap/hotfix/HSC-357
tkv00 Mar 18, 2026
4001b1e
hotfix: application log 설정 off
tkv00 Mar 18, 2026
8bb7ba2
Merge pull request #237 from one-year-gap/hotfix/HSC-357
tkv00 Mar 18, 2026
9d5e3c9
Merge pull request #244 from one-year-gap/release/HSC-377
tkv00 Mar 19, 2026
675fd51
Merge pull request #251 from one-year-gap/release/HSC-397
tkv00 Mar 19, 2026
10170e2
[HSC-399] hotfix: 동적 필드 누락 수정
tkv00 Mar 19, 2026
f62d859
Merge pull request #253 from one-year-gap/hotfix/HSC-399
tkv00 Mar 19, 2026
726a837
[HSC-400] feat: 공통 병목 모니터링 계측 기반 추가
tkv00 Mar 19, 2026
54a41f5
[HSC-400] feat: 추천·Kafka·사용자 로그 병목 메트릭 추가
tkv00 Mar 19, 2026
8c9a26b
Merge pull request #255 from one-year-gap/spike/HSC-400
tkv00 Mar 19, 2026
686b33c
[HSC-400] fix: meter cache 처리
tkv00 Mar 19, 2026
307eb41
Merge pull request #256 from one-year-gap/spike/HSC-400
tkv00 Mar 19, 2026
719a85c
[HSC-400] fix: '님' 중복 제거
tkv00 Mar 20, 2026
05cf2ee
Merge pull request #260 from one-year-gap/hotfix/null
tkv00 Mar 20, 2026
18ff97a
Merge branch 'origin/main' into release/HSC-413
tkv00 Mar 23, 2026
72fb484
Merge pull request #266 from one-year-gap/release/HSC-413
tkv00 Mar 23, 2026
306fe55
Merge pull request #268 from one-year-gap/hotfix/HSC-416
tkv00 Mar 23, 2026
bf74acf
[HSC-416] feat: 공통 운영 계측 기반 추가
tkv00 Mar 29, 2026
6b18e53
[HSC-416] feat: userlog 및 추천 관측 지표 확장
tkv00 Mar 29, 2026
6960191
Merge pull request #271 from one-year-gap/hotfix/HSC-416
tkv00 Mar 29, 2026
09ed377
[HSC-420] chore: 로그 추가
rettooo Mar 31, 2026
36f1061
Merge branch 'main' into hotfix/HSC-420
rettooo Mar 31, 2026
f7f5c2b
[HSC-420] refactor: 추천 Kafka 소비 로직 UseCase 분리
rettooo Mar 31, 2026
ebd1090
Merge pull request #274 from one-year-gap/hotfix/HSC-420
rettooo Mar 31, 2026
3d2d85c
[HSC-416] fix: Instant -> LocalDateTime 파싱 오류 수정
tkv00 Mar 31, 2026
731bdb8
Merge pull request #275 from one-year-gap/hotfix/HSC-416
tkv00 Mar 31, 2026
849ef32
[HSC-423] fix: admin internal log 비동기 분리
tkv00 Mar 31, 2026
e61a3e8
Merge pull request #277 from one-year-gap/perf/HSC-423
tkv00 Mar 31, 2026
cc63ac1
[HSC-423] fix: executor policy 변경
tkv00 Apr 1, 2026
28d1ec9
[HSC-423] fix: executor policy logging 추가
tkv00 Apr 1, 2026
f662f28
Merge pull request #278 from one-year-gap/perf/HSC-423
tkv00 Apr 1, 2026
7459331
[HSC-424] feat: 사용자 로그 admin dispatch 아웃박스 기반 구조 추가
tkv00 Apr 1, 2026
d463129
[HSC-424] feat: 사용자 로그 admin dispatch 아웃박스 연동
tkv00 Apr 1, 2026
8c6d92a
Merge pull request #280 from one-year-gap/perf/HSC-424
tkv00 Apr 1, 2026
1b5fdaa
[HSC-424] perf: 사용자 로그 아웃박스 배치 적재 적용
tkv00 Apr 1, 2026
58935c1
[HSC-424] perf: 사용자 로그 dispatch 재시도 기본값 완화
tkv00 Apr 1, 2026
589fea6
[HSC-424] fix: 사용자 로그 아웃박스 폴백 트랜잭션 분리
tkv00 Apr 1, 2026
3ed1845
Merge pull request #281 from one-year-gap/perf/HSC-424
tkv00 Apr 1, 2026
2316d8e
[HSC-424] fix: 로그 feature dispatch 날짜 및 enum 매핑 보완
tkv00 Apr 1, 2026
613fac5
Merge pull request #282 from one-year-gap/perf/HSC-424
tkv00 Apr 1, 2026
18b7442
[HSC-424] fix: 로그 outbox 서비스 컴파일 오류 정리
tkv00 Apr 1, 2026
bd63141
Merge pull request #283 from one-year-gap/perf/HSC-424
tkv00 Apr 1, 2026
f37ed15
[HSC-424] feat: 로그 feature 배치 엔드포인트 추가
tkv00 Apr 1, 2026
6a8ae4e
[HSC-424] feat: 로그 feature 아웃박스 배치 전송 적용
tkv00 Apr 1, 2026
4d24fae
Merge pull request #284 from one-year-gap/perf/HSC-424
tkv00 Apr 1, 2026
4964bcf
[HSC-424] feat: 로그 outbox 유실 원인 추적 메트릭 추가
tkv00 Apr 2, 2026
47f78e1
[HSC-424] fix: outbox error 메트릭 eager 등록
tkv00 Apr 2, 2026
aecf426
[HSC-425] hotfix: 쿼리 수정
bon0512 Apr 3, 2026
225832b
[HSC-425] hotfix: 캐시 환경변수
bon0512 Apr 3, 2026
4e15682
[HSC-425] hotfix: 캐시 의존성 추가
bon0512 Apr 3, 2026
e00682d
[HSC-425] hotfix: 관리자 통계 캐시 추가
bon0512 Apr 3, 2026
a7fe40b
[HSC-425] hotfix: 메인 캐시설정
bon0512 Apr 3, 2026
87fcbd1
[HSC-425] hotfix: 캐시 컨피그 추가
bon0512 Apr 3, 2026
9be5a01
[HSC-425] hotfix: 캐시 컨피그 리뷰 수정
bon0512 Apr 3, 2026
bfa6d3d
Merge pull request #287 from one-year-gap/hotfix/HSC-425
bon0512 Apr 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-cache'
implementation 'org.springframework.kafka:spring-kafka'
implementation 'com.github.ben-manes.caffeine:caffeine'
runtimeOnly 'software.amazon.msk:aws-msk-iam-auth:2.3.5'
runtimeOnly 'org.postgresql:postgresql'
compileOnly 'org.projectlombok:lombok'
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/site/holliverse/HolliverseApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@EnableCaching
@SpringBootApplication(
scanBasePackages = "site.holliverse"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
@Profile("admin")
public class HandleLogFeatureUseCase {

private static final ZoneId BASE_DATE_ZONE = ZoneId.of("Asia/Seoul");

private final CalculateLogChurnScoreService calculateLogChurnScoreService;

/**
Expand All @@ -35,7 +37,7 @@ public void execute(LogFeatureWebhookRequest request) {

calculateLogChurnScoreService.calculateAndStore(
request.memberId(),
LocalDate.from(request.timeStamp()),
resolveBaseDate(request.timeStamp()),
List.of(new LogFeatureEvent(
resolveEventId(request),
request.timeStamp(),
Expand All @@ -55,4 +57,11 @@ private long resolveEventId(LogFeatureWebhookRequest request) {
return Integer.toUnsignedLong((request.memberId() + "|" + request.eventType() + "|" + request.timeStamp()).hashCode());
}

private LocalDate resolveBaseDate(Instant timestamp) {
return Optional.ofNullable(timestamp)
.orElseGet(Instant::now)
.atZone(BASE_DATE_ZONE)
.toLocalDate();
}

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package site.holliverse.admin.application.usecase;

import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import site.holliverse.admin.query.dao.AdminRegionalMetricDao;
import site.holliverse.admin.query.dao.RegionalMetricRawData;
import site.holliverse.admin.web.dto.analytics.AdminRegionalMetricRequestDto;
import site.holliverse.shared.config.cache.CacheConfig;
import site.holliverse.shared.alert.AlertOwner;
import site.holliverse.shared.logging.SystemLogEvent;

Expand All @@ -24,6 +26,7 @@ public class RetrieveRegionalMetricUseCase {
@Transactional(readOnly = true)
@SystemLogEvent("admin.regional.metrics")
@AlertOwner("bm")
@Cacheable(cacheNames = CacheConfig.REGIONAL_METRICS_CACHE, key = "#requestDto.yyyymm()",sync = true)
public List<RegionalMetricRawData> execute(AdminRegionalMetricRequestDto requestDto) {
return adminRegionalMetricDao.findRegionalAverages(requestDto.yyyymm());
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package site.holliverse.admin.application.usecase;

import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import site.holliverse.admin.query.dao.AdminRegionalTopPlanDao;
import site.holliverse.admin.query.dao.RegionalSubscriberCountRawData;
import site.holliverse.admin.query.dao.RegionalTopPlanRawData;
import site.holliverse.shared.config.cache.CacheConfig;
import site.holliverse.shared.alert.AlertOwner;
import site.holliverse.shared.logging.SystemLogEvent;

Expand Down Expand Up @@ -43,6 +45,7 @@ public class RetrieveRegionalTopPlanUseCase {
@Transactional(readOnly = true)
@SystemLogEvent("admin.regional.topN")
@AlertOwner("bm")
@Cacheable(cacheNames = CacheConfig.REGIONAL_TOP_PLANS_CACHE, sync = true)
public List<RegionalTopPlanSummary> execute() {

// 지역별
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* 지역별 Top 요금제/가입자 수 집계를 담당하는 DAO.
* - 전지역 단위로 한 번에 집계한다.
* - 기준 데이터는 활성 구독만 사용한다.
*
* @author nonstop
* @version 1.0.0
* @since 2026-02-23
Expand All @@ -34,60 +35,82 @@ public class AdminRegionalTopPlanDao {

/**
* 전지역의 Top N 요금제명을 조회한다.
*
* 정렬 기준(지역 내부):
* 1) 요금제 가입자 수 내림차순
* 2) 요금제명 오름차순 (이유 : 요금제명 오름차순을 안하면 같은 구독자일시 매번 요금제명이 달라질 수 있음)
*
* 반환:
* 지역과 top3 요금제
*/
public List<RegionalTopPlanRawData> findTopPlansByAllProvinces(int limit) {
Field<String> province = ADDRESS.PROVINCE.as("province");
Field<Long> memberId = MEMBER.MEMBER_ID.as("memberId");
Field<String> planName = PRODUCT.NAME.as("planName");
// 지역별 순위를 만들기 위한 윈도우 함수(row_number)
Field<Integer> rankNo = DSL.rowNumber().over(
DSL.partitionBy(ADDRESS.PROVINCE)
.orderBy(DSL.countDistinct(MEMBER.MEMBER_ID).desc(), PRODUCT.NAME.asc())
).as("rankNo");

// 1단계: (지역, 요금제)별 가입자 수를 집계하고 지역 내부 순위를 계산
Table<?> ranked = dsl
.select(province, planName, rankNo)
//1. 먼저 지역 + 회원 + 요금제 기준으로 중복을 제거
// 원래 countDistinct(member_id)로 하던 일을 앞단의 distinct로 옮긴 단계였음.
Table<?> base = dsl
.selectDistinct(province, memberId, planName)
.from(SUBSCRIPTION)
.join(MEMBER).on(MEMBER.MEMBER_ID.eq(SUBSCRIPTION.MEMBER_ID))
.join(ADDRESS).on(ADDRESS.ADDRESS_ID.eq(MEMBER.ADDRESS_ID))
.join(PRODUCT).on(PRODUCT.PRODUCT_ID.eq(SUBSCRIPTION.PRODUCT_ID))
.where(SUBSCRIPTION.STATUS.isTrue())
.and(PRODUCT.PRODUCT_TYPE.eq(ProductTypeEnum.MOBILE_PLAN))
.groupBy(ADDRESS.PROVINCE, PRODUCT.NAME)
.asTable("ranked");
.asTable("base");
Field<String> baseProvince = base.field("province", String.class);
Field<String> basePlanName = base.field("planName", String.class);

Field<String> rankedProvince = ranked.field(province);
Field<String> rankedPlanName = ranked.field(planName);
Field<Integer> rankedRankNo = ranked.field(rankNo);
//2. 중복 제거된 결과에서 지역 + 요금제별 가입자 수를 카운트
// 개선안 : 여기서는 이미 회원 중복이 제거 됐으므로 countDistinct가 아니라 count(*)면 됨
Field<Integer> subscriberCount = DSL.count().as("subscriberCount");
Table<?> planCounts = dsl
.select(
baseProvince,
basePlanName,
subscriberCount
)
.from(base)
.groupBy(baseProvince, basePlanName)
.asTable("planCounts");

// 2단계: 지역별 순위가 limit 이하인 데이터만 추출
return dsl
Field<String> countedProvince = planCounts.field("province", String.class);
Field<String> countedPlanName = planCounts.field("planName", String.class);
Field<Integer> countedSubscriberCount = planCounts.field("subscriberCount", Integer.class);

// 3. 지역별로 가입자 수 내림차순, 요금제명 오름차순 기준 rank를 만듬
Field<Integer> rankNo = DSL.rowNumber().over(
DSL.partitionBy(countedProvince)
.orderBy(countedSubscriberCount.desc(), countedPlanName.asc())
).as("rankNo");

Table<?> ranked = dsl
.select(
rankedProvince,
rankedPlanName
countedProvince,
countedPlanName,
rankNo
)
.from(planCounts)
.asTable("ranked");

Field<String> rankedProvince = ranked.field("province", String.class);
Field<String> rankedPlanName = ranked.field("planName", String.class);
Field<Integer> rankedRankNo = ranked.field("rankNo", Integer.class);

// 4. 지역별 상위 N개만 추출하고 기존 DTO 형태로 반환
return dsl
.select(rankedProvince, rankedPlanName)
.from(ranked)
.where(rankedRankNo.le(limit))
.orderBy(
rankedProvince.asc(),
rankedRankNo.asc()
)
.orderBy(rankedProvince.asc(), rankedRankNo.asc())
.fetch(r -> new RegionalTopPlanRawData(
r.get(rankedProvince),
r.get(rankedPlanName)
));

}

/**
* 전지역 총 가입자 수를 조회한다.
*
* 규칙:
* - distinct(member_id) 기준
* - 활성 구독(status=true)만 포함
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import site.holliverse.admin.application.usecase.HandleLogFeatureUseCase;
import site.holliverse.admin.application.usecase.LogFeaturesUseCase;
import site.holliverse.admin.web.dto.log.LogFeatureWebhookRequest;
import site.holliverse.admin.web.dto.log.LogFeaturesRequestDto;

/**
* 실시간 로그 기반 feature customer -> admin 전송 로직
Expand All @@ -20,6 +22,7 @@
@RequiredArgsConstructor
public class InternalLogFeatureController {
private final HandleLogFeatureUseCase useCase;
private final LogFeaturesUseCase batchUseCase;


@PostMapping
Expand All @@ -29,4 +32,11 @@ public ResponseEntity<Void> receive (@RequestBody @Valid LogFeatureWebhookReques
return ResponseEntity.accepted().build();
}

@PostMapping("/batch")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

프로젝트 아키텍처 규칙(Rule 36) 및 일반 규칙에 따라 Admin API 엔드포인트는 반드시 /api/admin/... 경로를 포함해야 하며, 버전 정보가 앞에 와야 합니다 (/api/{version}/admin/...). 현재 클래스의 베이스 경로(/internal/v1/log-features)가 이 규칙을 위반하고 있으므로 수정이 필요합니다.

References
  1. Admin 엔드포인트는 @Profile("admin")과 @RequestMapping("/api/admin/...")을 가져야 함 (link)

public ResponseEntity<Void> receiveBatch(@RequestBody @Valid LogFeaturesRequestDto request) {
batchUseCase.execute(request);

return ResponseEntity.accepted().build();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package site.holliverse.customer.application.usecase.log;

import lombok.extern.slf4j.Slf4j;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Profile;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import site.holliverse.customer.integration.external.AdminLogFeaturesClient;
import site.holliverse.customer.persistence.entity.UserLogAdminDispatchOutbox;

import java.util.List;

/**
* admin log-feature 별도 executor로 분리
*/
@Slf4j
@Service
@Profile("customer")
@RequiredArgsConstructor
public class AdminLogFeatureDispatchService {

private final AdminLogFeaturesClient adminLogFeaturesClient;
private final UserLogAdminDispatchOutboxStateService stateService;

@Async("adminLogFeatureTaskExecutor")
public void dispatchBatch(List<UserLogAdminDispatchOutbox> rows) {
if (rows == null || rows.isEmpty()) {
return;
}

List<Long> eventIds = rows.stream()
.map(UserLogAdminDispatchOutbox::getEventId)
.toList();

try {
var result = adminLogFeaturesClient.sendLogFeaturesBatch(
rows.get(0).getMemberId(),
rows.stream()
.map(row -> new AdminLogFeaturesClient.BatchLogEvent(
row.getEventId(),
row.getEventTimestamp().toString(),
row.getEventType(),
row.getEventName(),
row.getPayload().path("event_properties")
))
.toList()
);

if (result.success()) {
stateService.markAcked(eventIds);
return;
}

stateService.markRetry(eventIds, result.errorMessage());
} catch (Exception e) {
stateService.markRetry(eventIds, e.getClass().getSimpleName() + ":" + e.getMessage());
}
}
}
Loading
Loading