Skip to content

Conversation

@claire-lemon
Copy link
Contributor

PR Description

개요

fix/dynamo-remove-undefinded-value

DynamoDB 배치 업데이트 시 발생하는 undefined 값 처리 및 ID 매핑 오류를 수정했습니다.


개선 내용

1. Undefined 값 처리 문제

문제 상황

  • DynamoDB는 기본적으로 undefined 값을 허용하지 않음
  • nested object나 array 내부의 undefined 값이 저장 시 에러 발생
    Pass options.removeUndefinedValues=true to remove undefined values from map/array/set
    
  • production 환경에서 실제 발생한 케이스 (user/T1019734)
    • activateToken, activateTokenTs 등의 필드에 undefined 포함

수정 내용

AbstractService (abstract-service.ts)

  • removeUndefined() 재귀 함수 추가
    • nested object의 모든 계층에서 undefined 제거
    • array 내부의 undefined 필터링
  • onlyValid !== false 옵션일 때 자동으로 undefined 제거
  • DynamoDB 에러 사전 방지

saveAllUpdates 테스트 추가 (abstract-service.spec.ts)

  • onlyValid: false → 에러 발생 검증
  • onlyValid: true → undefined 필터링 검증
  • default 동작 → undefined 필터링 검증
  • 배치/레거시 모드 모두 테스트 하여 결과 비교

2. 배치 모드 ID 매핑 오류

문제 상황

증상

  • saveAllUpdates({ useBatch: true }) 사용 시 데이터 저장/조회 실패
  • name, test 등의 필드가 undefined로 조회됨

원인

  • short id (child-batch-100-50)와 full partition key (TT:test:child-batch-100-50) 혼선
  • DynamoService.mupdateItem()에서 잘못된 partition key 사용
  • 기존 항목 대신 새로운 빈 항목이 생성됨

⚠️ 테스트 환경 설정 오류

  • instance() 호출 시 타입을 지정하지 않으면 dummy storage로 테스트됨
  • dummy storage는 실제 DynamoDB와 다르게 동작하여 ID 매핑 오류를 감지하지 못함
  • 모든 테스트가 통과하여 문제가 없다고 잘못 판단함
  • 실제 DynamoDB 환경에서 테스트하며 ID 매핑 오류 발견 및 개선 완료

수정 내용

DynamoService (dynamo-service.ts)

  • mupdateItem()에서 actualId 로직 추가
  • partition key(_id)를 우선 사용하도록 수정
    const actualId = (rest as any)[this.options.idName] || id;
    const payload = this.prepareSaveItem(actualId, rest as unknown as T);

ProxyStorageService (proxy-storage-service.ts)

  • idMap 도입: short id → full _id 매핑 관계 저장
  • mupdate() 결과 반환 시 올바른 full _id로 복원
    • success/failed 모두에 매핑 복원 적용

AbstractProxy (abstract-service.ts)

  • 배치 모드: 전체 모델 전달
  • 레거시 모드: 변경된 필드만 전달

배치 모드에서 전체 모델을 전달하는 이유

  • AWS DynamoDB의 BatchWriteItem API는 UpdateRequest를 지원하지 않음
  • 배치 처리를 위해 PutRequest를 사용해야 함
  • PutRequest는 항목 전체를 덮어쓰기하므로 전체 모델이 필요
    BatchWriteItem API 지원:
    ✅ PutRequest (전체 덮어쓰기) - 배치 가능
    ✅ DeleteRequest (삭제) - 배치 가능  
    ❌ UpdateRequest (부분 업데이트) - 지원 안 함
    

테스트 코드 개선

  • Before: instance() → dummy storage 사용
  • After: instance('real') → 실제 DynamoDB 사용
  • mock 코드 제거, 실제 storage 동작 검증
  • _id 검증을 full partition key 형태로 수정
  • 테스트 전/후 cleanup으로 데이터 격리

성능 테스트

  • 100, 1000 children 복제 시나리오
  • 배치 vs 레거시 모드 성능 비교
  • 성능 리포트 자동 생성 (coverage/perf-child-replication-*.json)

@claire-lemon claire-lemon changed the base branch from develop to fix/lambda-kms-dns-error-getaddrinfo-ebusy January 2, 2026 05:25
Copy link
Member

@steve-lemon steve-lemon left a comment

Choose a reason for hiding this comment

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

LGTM

@steve-lemon
Copy link
Member

@claire-lemon proxy-storage 에서 my_parallel() 이용과 mget() 의 동질성 검증 강화해줘요.

Copy link
Member

@aiden-lemon aiden-lemon left a comment

Choose a reason for hiding this comment

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

LGTM; 확인했습니다!

Copy link
Member

@steve-lemon steve-lemon left a comment

Choose a reason for hiding this comment

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

LGTM

result.failed = (res.failed || []).map(toModel);
const res = await this.$dynamo.mupdateItem(items);ß
result.success = (res.success as unknown as T[]) || [];
result.failed = (res.failed as unknown as T[]) || [];
Copy link
Member

Choose a reason for hiding this comment

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

NOTE! failed 가 발생하면 안됨! 만일 그렇다면 명시적인 경우에만 retry 로직 필요함. 그 외에는 모두 throw 해줘야 이후 알수 있음

@steve-lemon steve-lemon merged commit 3c81931 into fix/lambda-kms-dns-error-getaddrinfo-ebusy Jan 5, 2026
@steve-lemon steve-lemon deleted the fix/dynamo-remove-undefinded-value branch January 5, 2026 01:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants