Conversation
📝 WalkthroughWalkthrough가구 큐레이션 시스템에 RAW 소스를 추가하여 NAVER와 RAW 두 가지 데이터 소스를 병렬로 처리하도록 확장했습니다. 새로운 Changes
Sequence DiagramsequenceDiagram
actor Scheduler as Curation<br/>Scheduler
participant NaverSvc as NaverShop<br/>Service
participant ImgHash as ImageHash<br/>Service
participant RawSvc as CurationRaw<br/>ProductService
participant SaveSvc as CurationFurniture<br/>Service
participant DB as Database
Note over Scheduler,DB: NAVER Source Processing
Scheduler->>Scheduler: fetchNaverCurationWithRetry()
Scheduler->>NaverSvc: fetch NAVER products
NaverSvc-->>Scheduler: product list
Scheduler->>ImgHash: rank by similarity
ImgHash-->>Scheduler: ranked products
Scheduler->>SaveSvc: saveCurationResults(NAVER)
SaveSvc->>DB: save curations + source=NAVER
DB-->>SaveSvc: saved results
SaveSvc-->>Scheduler: completed
Note over Scheduler,DB: RAW Source Processing
Scheduler->>Scheduler: fetchRawCurationWithRetry()
Scheduler->>RawSvc: fetch RAW candidates
RawSvc->>DB: query curation_raw_products
DB-->>RawSvc: raw products
RawSvc-->>Scheduler: candidate list
Scheduler->>ImgHash: rank by similarity
ImgHash-->>Scheduler: ranked products
Scheduler->>SaveSvc: saveCurationResults(RAW)
SaveSvc->>DB: save curations + source=RAW
DB-->>SaveSvc: saved results
SaveSvc-->>Scheduler: completed
Note over Scheduler,DB: Result Aggregation
Scheduler->>Scheduler: merge NAVER + RAW results
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
src/main/java/or/sopt/houme/domain/furniture/service/facade/FurnitureFacadeImpl.java (1)
44-45:⚠️ Potential issue | 🟡 Minor종료 시간 로그가 시작 시간을 찍고 있어요
Line 44-45에서
formatted를 한 번만 캡처하고, Line 105의 "큐레이션 종료" 로그에서도 같은 값을 사용하고 있어서 실제 종료 시각이 아닌 시작 시각이 찍힙니다. 디버깅이나 모니터링 시 혼란을 줄 수 있어요.🛠️ 수정 제안
- log.info("큐레이션 종료:{}",formatted); + String endFormatted = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + log.info("큐레이션 종료:{}", endFormatted);Also applies to: 105-105
src/main/java/or/sopt/houme/domain/furniture/model/entity/CurationRawProduct.java (1)
115-135:⚠️ Potential issue | 🟡 Minor새로 추가된 필드들을 업데이트할 방법이 없어요
brand,baseShippingFee,freeShippingCondition필드는 엔티티에 추가됐지만, 생성 후 이들을 업데이트할 수 있는 방법이 없네요. 현재of()메서드는 외부 source(Naver)에서 제공하는 데이터만 포함하고 있는데,furnitureTag처럼updateBrand(),updateShippingFees()같은 update 메서드가 있거나updateFrom()에 이 필드들을 추가해야 할 것 같습니다. 아니면 이 필드들이 다른 경로로 채워진다면 그 로직을 명확히 해주면 좋을 것 같아요.src/main/java/or/sopt/houme/domain/furniture/infrastructure/dto/external/naverShop/FurnitureProductsInfoResponse.java (1)
29-54:⚠️ Potential issue | 🟡 Minor7-param
of()에서jjymCount만0L, 나머지 신규 필드는null— 기본값 혼재
jjymCount는0L로,listPrice/discountRate/discountPrice/brandName은null로 초기화하고 있는데, 소비 측에서 null 체크 누락 시 NPE 가능성이 있어요. 기본값 정책을 통일하거나, 소비 측에서 null-safe 처리가 되어 있는지 확인이 필요합니다.
🤖 Fix all issues with AI agents
In
`@src/main/java/or/sopt/houme/domain/furniture/model/entity/CurationFurniture.java`:
- Around line 20-25: You changed the unique constraint in entity
CurationFurniture from (furniture_tag_id, rank) to (furniture_tag_id, source,
rank) (constraint name uk_curation_furniture_tag_source_rank); before applying
the migration, run a data-check and cleanup: query existing rows grouped by
furniture_tag_id and rank to find cases with multiple distinct source values,
then either populate missing source values consistently or remove/merge
duplicates so inserting the new constraint will not fail; include this
validation/cleanup as a pre-migration step in your migration script or runbook
and re-run the check after changes to ensure no (furniture_tag_id, rank)
duplicates across different source remain.
In
`@src/main/java/or/sopt/houme/domain/furniture/service/CurationFurnitureServiceImpl.java`:
- Around line 122-123: The repository method deleteByFurnitureTagAndSource
should be annotated with `@Modifying`(clearAutomatically = true) to ensure Spring
Data executes it as a bulk DELETE and automatically synchronizes the persistence
context; update the repository interface where
deleteByFurnitureTagAndSource(...) is declared to add
`@Modifying`(clearAutomatically = true) (and import
org.springframework.data.jpa.repository.Modifying) so subsequent calls in
CurationFurnitureServiceImpl (which calls
curationFurnitureRepository.deleteByFurnitureTagAndSource and saveAll) won't
suffer from stale persistence-context state.
In
`@src/main/java/or/sopt/houme/domain/furniture/service/facade/FurnitureFacadeImpl.java`:
- Around line 54-62: The call to naverShopService.search(keyword, 50) can return
null or an empty list and must be checked before passing to
imageHashService.rankByImageSimilarity; update the code around where products is
assigned (from naverShopService.search) so that if products == null ||
products.isEmpty() you short-circuit (e.g., set rankedInfos to an empty list or
skip the rankByImageSimilarity call and return the empty result) instead of
calling imageHashService.rankByImageSimilarity(furnitureTag.getFurnitureUrl(),
products, CURATION_LIMIT); ensure you follow the same null/empty handling as the
V2 method to avoid NPEs.
🧹 Nitpick comments (13)
src/main/java/or/sopt/houme/domain/furniture/model/entity/RecommendFurniture.java (1)
14-17:source단독 인덱스는 실효성이 낮을 수 있어요.
source컬럼은 현재NAVER/RAW두 값뿐이라 카디널리티가 매우 낮습니다. 이런 경우 DB 옵티마이저가 인덱스를 타지 않고 풀스캔하는 게 더 효율적이라 판단할 가능성이 높아요. 게다가uk_source_furniture_product_id유니크 제약이 이미(source, furniture_product_id)복합 인덱스를 내부적으로 생성하므로,source선행 컬럼 기반 조회는 이미 커버됩니다.불필요한 인덱스는 쓰기 성능에 오버헤드를 주니, 실제 쿼리 패턴에서
source단독 필터가 빈번한지 확인해보고 제거를 고려해보세요.🔧 인덱스 제거 제안
indexes = { `@Index`(name = "idx_furniture_product_id", columnList = "furniture_product_id"), - `@Index`(name = "idx_recommend_source", columnList = "source") },src/main/java/or/sopt/houme/domain/furniture/service/CurationRawProductService.java (2)
28-58:NaverFurnitureProductDto를 RAW 소스에도 재사용하는 부분 — 나중에 리네이밍 고려해보면 좋겠어요.로직 자체는 정확합니다. null 가드, 필터링, 중복 제거(first wins) 모두 잘 되어 있어요.
다만
NaverFurnitureProductDto라는 이름이 네이버 전용처럼 보이는데 RAW 소스에서도 동일하게 사용하고 있어서, 나중에FurnitureProductDto같은 소스-중립적인 이름으로 리네이밍하면 코드 읽을 때 혼란을 줄일 수 있을 것 같습니다. 지금 당장은 기능에 문제없으니 급하진 않고요.
39-57:Collectors.toMap의 결과 순서가 비결정적이에요 — 현재 사용 맥락에서는 괜찮아 보이지만 참고용으로.
Collectors.toMap은 내부적으로HashMap을 사용해서.values().stream().toList()결과의 순서가 보장되지 않습니다. 이 메서드의 결과가 이후 유사도 기반으로 정렬/랭킹된다면 문제없지만, 만약 이 단계에서 특정 순서(예: DB 조회 순서)를 유지해야 하는 요구사항이 생기면LinkedHashMap을 사용하는toMap오버로드로 변경이 필요합니다.src/main/java/or/sopt/houme/domain/furniture/service/facade/FurnitureFacadeImpl.java (2)
106-109:Streamfully-qualified 사용 & 응답 합치기 로직
java.util.stream.Stream.concat(...)대신 import를 추가해서 쓰면 더 깔끔합니다. 사소하지만 가독성 차이가 있어요.♻️ 리팩터 제안
파일 상단 import 추가:
import java.util.stream.Stream;return FurnitureProductsInfoResponse.of( user.getName(), - java.util.stream.Stream.concat(naverInfos.stream(), rawInfos.stream()).toList() + Stream.concat(naverInfos.stream(), rawInfos.stream()).toList() );
126-128:CURATION_LIMIT상수가 ForPlan 메서드에서는 미적용Line 31에
CURATION_LIMIT = 5를 잘 정의해두셨는데, Line 128과 170에서는 여전히 하드코딩5를 쓰고 있어요. 나중에 값 변경 시 누락될 수 있으니 통일해두면 좋겠습니다.Also applies to: 168-170
src/main/java/or/sopt/houme/domain/furniture/repository/RecommendFurnitureRepository.java (1)
11-11:java.util.Optionalfully-qualified 사용import로 빼면 더 깔끔해요. 사소한 부분이지만요.
♻️ 리팩터 제안
파일 상단에 import 추가:
import java.util.Optional;- java.util.Optional<RecommendFurniture> findBySourceAndFurnitureProductId(CurationSource source, Long furnitureProductId); + Optional<RecommendFurniture> findBySourceAndFurnitureProductId(CurationSource source, Long furnitureProductId);src/main/java/or/sopt/houme/domain/furniture/service/RecommendFurnitureServiceImpl.java (2)
48-51:existsBy+findBy이중 쿼리 →findBy하나로 충분해요
existsBySourceAndFurnitureProductId로 조회한 뒤 바로findBySourceAndFurnitureProductId를 또 호출하고 있어서, 같은 조건으로 DB 쿼리가 2번 나가요.findBy만 호출해서Optional로 분기하면 쿼리 1회로 줄일 수 있고, exists 체크와 find 사이에 데이터가 변경되는 TOCTOU 문제도 자연스럽게 사라집니다.♻️ 개선 제안
- boolean exists = recommendFurnitureRepository.existsBySourceAndFurnitureProductId(source, productId); - if (exists) { - entity = recommendFurnitureRepository.findBySourceAndFurnitureProductId(source, productId) - .orElseThrow(); - } else { + var existing = recommendFurnitureRepository.findBySourceAndFurnitureProductId(source, productId); + if (existing.isPresent()) { + entity = existing.get(); + } else { entity = RecommendFurniture.from( furnitureProductInfo.furnitureProductImageUrl(), furnitureProductInfo.furnitureProductSiteUrl(), furnitureProductInfo.furnitureProductName(), furnitureProductInfo.furnitureProductMallName(), productId, source ); entity = recommendFurnitureRepository.save(entity); }
23-29:saveRecommendFurniture가saveSingleRecommendFurniture를 그대로 위임만 하고 있어요public 메서드가 private 메서드를 단순 호출만 하는 구조라 불필요한 indirection입니다. 현재 로직이 확장될 예정이 아니라면 하나로 합치는 게 깔끔해요.
src/main/java/or/sopt/houme/domain/furniture/infrastructure/dto/external/naverShop/FurnitureProductsInfoResponse.java (1)
13-27:naverShop패키지에 있지만 RAW 소스에서도 사용되는 공용 DTO에요
FurnitureProductInfo가 이제 NAVER뿐 아니라 RAW 소스의 큐레이션 결과도 담고 있어서,naverShop패키지에 위치하는 게 의미적으로 안 맞아요. 필드도 14개까지 늘어났고요. 지금 당장은 아니더라도, 향후 공통 DTO 패키지로 분리하거나 소스별 DTO를 나누는 걸 고려해보면 좋겠습니다.src/main/java/or/sopt/houme/domain/furniture/service/CurationFurnitureServiceImpl.java (2)
56-80:rawMeta != null반복 체크 — 빈 기본 객체로 간소화 가능Lines 59~76에서
rawMeta != null ? rawMeta.xxx() : ...패턴이 6번 반복돼요. 빈 기본값을 가진RawProductMeta를 하나 만들어두면 null 분기 없이 깔끔해집니다.♻️ 개선 제안
RawProductMeta에 기본 빈 인스턴스를 추가:private static final RawProductMeta EMPTY = new RawProductMeta( List.of(), List.of(), null, null, null, null );그 후 매핑 시:
- RawProductMeta rawMeta = rawMetaByProductId.get(recommendFurniture.getFurnitureProductId()); - List<String> colors = rawMeta != null ? rawMeta.colors() : List.of(); - List<String> clientColors = rawMeta != null ? rawMeta.clientColors() : List.of(); + RawProductMeta rawMeta = rawMetaByProductId.getOrDefault( + recommendFurniture.getFurnitureProductId(), RawProductMeta.EMPTY);이후
rawMeta.colors(),rawMeta.listPrice()등 직접 접근 가능.
136-216:buildRawMetaByProductId메서드가 80줄 — 가독성 면에서 분리 고려color 집계 로직(Lines 177-197)과 최종 meta 조립 로직(Lines 199-214)을 별도 private 메서드로 분리하면 각 단계의 의도가 명확해져요. 지금 당장 급하진 않지만, 이 메서드가 더 커지기 전에 나누는 게 좋겠습니다.
src/main/java/or/sopt/houme/domain/furniture/infrastructure/scheduler/CurationFurnitureScheduler.java (2)
109-133:fetchNaverCurationWithRetry와fetchRawCurationWithRetry가 거의 동일한 코드에요로그 메시지와 내부 호출 메서드만 다르고 retry 구조는 완전히 같아서, 공통 retry 헬퍼로 추출하면 중복을 줄일 수 있어요.
♻️ 공통 retry 헬퍼 제안
+ private List<FurnitureProductsInfoResponse.FurnitureProductInfo> fetchWithRetry( + FurnitureTag furnitureTag, + java.util.function.Function<FurnitureTag, List<FurnitureProductsInfoResponse.FurnitureProductInfo>> fetcher, + String sourceName + ) { + for (int attempt = 1; attempt <= MAX_RETRY; attempt++) { + try { + return fetcher.apply(furnitureTag); + } catch (Exception e) { + log.warn("{} 큐레이션 배치 실패: tagId={}, attempt={}", sourceName, furnitureTag.getId(), attempt, e); + sleep(RETRY_BACKOFF_MILLIS * attempt); + } + } + return List.of(); + }호출부:
List<...> naverInfos = fetchWithRetry(furnitureTag, this::fetchNaverCurationInfos, "네이버"); List<...> rawInfos = fetchWithRetry(furnitureTag, this::fetchRawCurationInfos, "RAW");
29-31:MAX_RETRY = 2는 최대 시도 횟수가 2회라는 의미 — 네이밍 주의보통
MAX_RETRY라고 하면 "재시도 횟수"로 읽히는데, 여기서는attempt <= MAX_RETRY이므로 사실상 총 시도 2회(= 재시도 1회)예요. 의도된 동작이라면 OK인데, 혼동 여지가 있으니MAX_ATTEMPTS로 바꾸거나 값을 3으로 조정하는 것도 고려해보세요.
| uniqueConstraints = { | ||
| @UniqueConstraint( | ||
| name = "uk_curation_furniture_tag_rank", | ||
| columnNames = {"furniture_tag_id", "rank"} | ||
| name = "uk_curation_furniture_tag_source_rank", | ||
| columnNames = {"furniture_tag_id", "source", "rank"} | ||
| ) | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# 마이그레이션 파일 디렉토리 탐색
find . -type d \( -name "db" -o -name "migration" -o -name "migrations" -o -name "flyway" -o -name "liquibase" \) 2>/dev/null | head -20Repository: TEAM-HOUME/HOUME-SERVER
Length of output: 49
🏁 Script executed:
# SQL/마이그레이션 파일 찾기
git ls-files | grep -E '\.(sql|xml|yaml)$' | grep -iE '(db|migration|flyway|liquibase)' | head -30Repository: TEAM-HOUME/HOUME-SERVER
Length of output: 49
🏁 Script executed:
# 기존 constraint 이름 검색
rg "uk_curation_furniture_tag" --type=sql --type=yaml --type=xml 2>/dev/null || echo "No matches found"Repository: TEAM-HOUME/HOUME-SERVER
Length of output: 83
🏁 Script executed:
# Hibernate DDL 설정 확인
fd -e properties -e yml | xargs rg "hibernate.ddl|spring.jpa.hibernate" 2>/dev/nullRepository: TEAM-HOUME/HOUME-SERVER
Length of output: 51
🏁 Script executed:
# CurationFurniture.java 전체 내용 확인
cat src/main/java/or/sopt/houme/domain/furniture/model/entity/CurationFurniture.javaRepository: TEAM-HOUME/HOUME-SERVER
Length of output: 2258
유니크 제약 변경 - 데이터 정합성 확인 필요
제약 조건이 (furniture_tag_id, rank) → (furniture_tag_id, source, rank)로 변경된 건 로직상 정확해요. NAVER/RAW 각각 동일 태그에서 rank 1~5를 가질 수 있어야 하니까요.
다만 한 가지 확인 필요한데, 만약 현재 운영 DB에 기존 제약 조건으로 인해 (furniture_tag_id, rank) 조합이 유일한 데이터들이 있다면, 새 제약이 적용될 때 데이터 정합성 이슈가 발생할 수 있습니다. 예를 들어 같은 tag + rank지만 서로 다른 source의 데이터가 남아있으면 제약 위반이 됩니다.
마이그레이션 전에 기존 데이터를 확인하고, 필요하면 source 값을 먼저 채우거나 중복 데이터를 정리하는 절차가 필요할 것 같습니다.
🤖 Prompt for AI Agents
In
`@src/main/java/or/sopt/houme/domain/furniture/model/entity/CurationFurniture.java`
around lines 20 - 25, You changed the unique constraint in entity
CurationFurniture from (furniture_tag_id, rank) to (furniture_tag_id, source,
rank) (constraint name uk_curation_furniture_tag_source_rank); before applying
the migration, run a data-check and cleanup: query existing rows grouped by
furniture_tag_id and rank to find cases with multiple distinct source values,
then either populate missing source values consistently or remove/merge
duplicates so inserting the new constraint will not fail; include this
validation/cleanup as a pre-migration step in your migration script or runbook
and re-run the check after changes to ensure no (furniture_tag_id, rank)
duplicates across different source remain.
| curationFurnitureRepository.deleteByFurnitureTagAndSource(furnitureTag, source); | ||
| curationFurnitureRepository.saveAll(curations); |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# CurationFurnitureRepository 파일 찾기
find . -name "*CurationFurnitureRepository*" -type fRepository: TEAM-HOUME/HOUME-SERVER
Length of output: 157
🏁 Script executed:
#!/bin/bash
# deleteByFurnitureTagAndSource 메서드와 `@Modifying` 설정 확인
rg -n -B2 -A5 'deleteByFurnitureTagAndSource' --type=javaRepository: TEAM-HOUME/HOUME-SERVER
Length of output: 1604
🏁 Script executed:
cat -n src/main/java/or/sopt/houme/domain/furniture/repository/CurationFurnitureRepository.javaRepository: TEAM-HOUME/HOUME-SERVER
Length of output: 1030
deleteByFurnitureTagAndSource 메서드에 @Modifying 애노테이션 추가 필요
확인 결과 리포지토리의 deleteByFurnitureTagAndSource 메서드에 @Modifying 애노테이션이 없네요. 이 derived query 메서드는 Spring Data가 bulk DELETE 쿼리로 구현하는데, @Modifying(clearAutomatically = true)를 추가해야 persistence context와의 동기화 문제를 방지할 수 있어요. 현재 상태면 delete 이후 다른 영속성 컨텍스트 작업에서 예상치 못한 동작이 발생할 수 있습니다.
🤖 Prompt for AI Agents
In
`@src/main/java/or/sopt/houme/domain/furniture/service/CurationFurnitureServiceImpl.java`
around lines 122 - 123, The repository method deleteByFurnitureTagAndSource
should be annotated with `@Modifying`(clearAutomatically = true) to ensure Spring
Data executes it as a bulk DELETE and automatically synchronizes the persistence
context; update the repository interface where
deleteByFurnitureTagAndSource(...) is declared to add
`@Modifying`(clearAutomatically = true) (and import
org.springframework.data.jpa.repository.Modifying) so subsequent calls in
CurationFurnitureServiceImpl (which calls
curationFurnitureRepository.deleteByFurnitureTagAndSource and saveAll) won't
suffer from stale persistence-context state.
| log.info("네이버 API 호출을 시작합니다"); | ||
| String keyword = furnitureTag.getSearchKeyword(); | ||
| List<NaverFurnitureProductDto> products = naverShopService.search(keyword, 50); | ||
|
|
||
| // 2. FastAPI 호출 → 유사도 기반 상위 상품 리스트만 반환 | ||
| // 12/05 FAST API 삭제 | ||
| log.info("유사도 기반 네이버 상품 조회를 시작합니다"); | ||
| List<FurnitureProductsInfoResponse.FurnitureProductInfo> rankedInfos = | ||
| imageHashService.rankByImageSimilarity(furnitureTag.getFurnitureUrl(), products, CURATION_LIMIT); |
There was a problem hiding this comment.
네이버 API 응답 null/empty 체크 누락
naverShopService.search(keyword, 50) 반환값이 null이거나 빈 리스트일 때, Line 62의 rankByImageSimilarity로 바로 넘기면 NPE가 발생할 수 있어요. V2 메서드(Line 159)에서는 products == null || products.isEmpty() 체크를 하고 있는데, 여기는 빠져 있네요.
🐛 수정 제안
log.info("네이버 API 호출을 시작합니다");
String keyword = furnitureTag.getSearchKeyword();
List<NaverFurnitureProductDto> products = naverShopService.search(keyword, 50);
+
+ if (products == null || products.isEmpty()) {
+ naverInfos = List.of();
+ } else {
// 2. FastAPI 호출 → 유사도 기반 상위 상품 리스트만 반환
// 12/05 FAST API 삭제
log.info("유사도 기반 네이버 상품 조회를 시작합니다");
List<FurnitureProductsInfoResponse.FurnitureProductInfo> rankedInfos =
imageHashService.rankByImageSimilarity(furnitureTag.getFurnitureUrl(), products, CURATION_LIMIT);
// 2-1. 최종반환된 리스트를 기반으로 추천가구 엔티티 저장하고, 큐레이션 결과 저장
log.info("네이버 큐레이션 결과 저장");
naverInfos = curationFurnitureService.saveCurationResults(
furnitureTag,
rankedInfos,
CurationSource.NAVER
);
+ }🤖 Prompt for AI Agents
In
`@src/main/java/or/sopt/houme/domain/furniture/service/facade/FurnitureFacadeImpl.java`
around lines 54 - 62, The call to naverShopService.search(keyword, 50) can
return null or an empty list and must be checked before passing to
imageHashService.rankByImageSimilarity; update the code around where products is
assigned (from naverShopService.search) so that if products == null ||
products.isEmpty() you short-circuit (e.g., set rankedInfos to an empty list or
skip the rankByImageSimilarity call and return the empty result) instead of
calling imageHashService.rankByImageSimilarity(furnitureTag.getFurnitureUrl(),
products, CURATION_LIMIT); ensure you follow the same null/empty handling as the
V2 method to avoid NPEs.
📣 Related Issue
📝 Summary
🙏 Question & PR point
겨울 TF팀에서 진행한 회의 결과, 궁극적으로 네이버 API의 의존성을 끊고 모든 데이터를 프리셋으로 만들어두고 거기서 데이터를 제공 할 수 있도록 로직을 수정하는 것으로 결정되었습니다.
수집의 데이터를 큐레이션 과정에서 정상적으로 내려줄 수 있는 로직을 만들게 되었습니다.
이 과정에서 네이버 API의 로직을 최대한 재사용하여 큐레이션을 진행할 수 있도록 구현하였습니다.
로직은 다음과 같습니다.
사실상 거의 동일한 로직이고 source만 다르다고 이해하시면 될 것 같습니다.
해당 PR까지가 B-1의 마무리 PR이 될 것 같습니다.
이후에는 모든 의사결정을 @PBEM22 @kbt82883 와 함께 회의 후 진행하도록 하겠습니다.
@maehwasoo API 스펙 확인해보시고 컨펌주시길 바랍니다!
📬 Postman
해당 PR은 프리셋 데이터가 모두 입력된 이후에 머지하도록 하겠습니다.
Summary by CodeRabbit
릴리스 노트