Feature Store 일부 값만 바꾼다…UpdateRecord의 네 가지 제한

AWS가 2026년 9월 8일 Amazon SageMaker Feature Store의 특성 단위 쓰기 API인 UpdateRecord를 정식 출시했다. Techseen의 출시 브리핑 도 같은 날 공개된 기능으로 확인했으며, Feature Store가 제공되는 AWS 리전에서 이용할 수 있다고 전했다.
이 API는 기존 온라인 레코드에서 지정한 특성 값만 원자적으로 바꾸고 요청에서 뺀 값은 그대로 보존한다. AWS가 9월 8일 공개한 UpdateRecord 출시 설명 에 따르면 애플리케이션은 전체 레코드를 먼저 읽어 병합한 뒤 PutRecord로 다시 쓰던 과정을 한 번의 호출로 줄일 수 있다. 다만 기존 레코드만 수정하는 비업서트 API이며, Standard 계층에서는 Standard_V2 형식이 필요하다.
요청에는 식별자와 바꿀 특성만 넣는다

UpdateRecord는 POST /FeatureGroup/{FeatureGroupName}/Record 경로를 사용한다. 요청 본문에는 대상 레코드를 가리키는 RecordIdentifierValueAsString과 변경할 값을 담은 Features가 필수다. TargetStores와 TtlDuration은 필요할 때만 지정한다.
예를 들어 이미 존재하는 user_123 레코드에서 risk_score와 last_login만 바꾸려면 Features에 두 특성의 FeatureName과 값을 넣는다. balance나 customer_segment를 보내지 않았다면 그 값은 삭제되거나 초기화되지 않는다. 성공한 호출은 HTTP 200과 빈 응답 본문을 반환하므로 응답에서 갱신된 전체 레코드를 받을 수 있다고 가정해서는 안 된다.
EventTime을 갱신하려면 특성 그룹에서 이벤트 시간으로 정의된 특성을 Features에 포함한다. EventTime을 생략하면 지정한 특성 값은 바뀌지만 레코드에 저장된 기존 EventTime은 유지된다. 서로 다른 주기로 작동하는 파이프라인이 각자 담당하는 특성만 쓰는 경우에는 공통 레코드를 읽어 로컬에서 합치는 단계가 필요 없어질 수 있다.
PutRecord와 역할이 갈린다
PutRecord는 새 레코드를 만들 수 있고 전체 레코드를 기록하는 데 사용된다. 반면 UpdateRecord는 이미 있는 레코드를 수정할 뿐 새 식별자를 생성하지 않는다. 신규 레코드가 들어올 수 있는 수집 경로라면 PutRecord로 생성하거나 생성과 갱신을 구분해야 한다.
기존 부분 갱신 흐름은 대개 GetRecord로 모든 값을 읽고, 애플리케이션에서 변경분을 병합한 뒤 PutRecord로 전체 레코드를 다시 보내는 구조였다. 여러 생산자가 비슷한 시점에 서로 다른 특성을 수정하면 오래된 복사본을 기준으로 한 전체 쓰기가 다른 변경을 덮을 수 있다. UpdateRecord는 서비스가 선택된 값만 원자적으로 병합하므로 이 읽기와 애플리케이션 측 병합을 제거한다.
온라인 저장소와 오프라인 저장소가 함께 연결된 특성 그룹에서는 온라인 레코드에 선택된 값이 반영되고, 오프라인 저장소에는 갱신 뒤의 전체 레코드 스냅샷이 복제된다. 따라서 실시간 조회용 값과 학습·이력 분석용 데이터 흐름을 따로 조립할 필요는 없지만, UpdateRecord가 특성 그룹의 스키마를 바꾸거나 레코드 식별자를 수정하는 수단은 아니다.
운영 전 확인할 네 가지 제한

AWS의 UpdateRecord API 명세 는 적용 범위와 실패 조건을 다음 네 가지로 규정한다.
- 기존 온라인 레코드가 있어야 한다. 대상 레코드는 온라인 저장소에 이미 존재해야 한다. 레코드가 없거나 소프트 삭제된 상태면 ResourceNotFound와 HTTP 404가 반환된다. 처음 적재할 때 OfflineStore에만 기록한 레코드도 수정할 수 없다.
- 온라인 저장 유형이 제한된다. UpdateRecord는 Standard_V2 또는 InMemory 온라인 저장소를 사용하는 특성 그룹에서만 작동한다. TargetStores를 직접 지정한다면 OnlineStore를 반드시 포함해야 하며, OnlineStore만 또는 OnlineStore와 OfflineStore를 함께 선택할 수 있다.
- 호출당 최대 100개 특성이다. Features에는 적어도 한 개의 값이 필요하고 한 번에 100개까지만 갱신할 수 있다. 변경할 값이 이를 넘으면 요청을 나눠야 하므로, 넓은 레코드를 사실상 전부 교체하는 작업은 PutRecord와 호출 수 및 원자성 범위를 비교해야 한다.
- EventTime과 TTL 규칙을 함께 지켜야 한다. 요청의 EventTime이 현재 레코드보다 오래되면 전체 갱신이 ConflictException과 HTTP 409로 거부된다. 같거나 더 최신이면 적용되며, EventTime을 보내지 않으면 기존 시간이 유지된다. TtlDuration을 지정하면서 EventTime을 포함하지 않으면 ValidationError와 HTTP 400이 발생한다.
오래된 EventTime으로 발생한 409는 단순한 일시 장애가 아니다. 최신 레코드보다 앞선 이벤트의 쓰기를 막는 순서 검증 결과이므로, 같은 요청을 그대로 반복해도 조건이 달라지지 않는다. 지연 도착 이벤트를 처리하는 파이프라인은 최신 상태를 기준으로 다시 계산할지 해당 이벤트를 제외할지 결정해야 한다.
TTL은 EventTime과 TtlDuration을 더한 시점에 만료되도록 계산된다. TtlDuration을 생략하면 기존 TTL 설정이 유지되므로 일반적인 특성 갱신이 레코드 수명을 자동으로 없애지는 않는다. 반대로 만료 기간을 의도적으로 바꾸는 요청에는 유효한 EventTime도 함께 구성해야 한다.
Standard 그룹은 전환 방식까지 따져야 한다

새 Standard 계층 특성 그룹은 생성할 때 OnlineStoreConfig의 StorageType을 Standard_V2로 지정해야 특성 단위 쓰기를 사용할 수 있다. In-Memory 계층은 별도의 새 형식으로 바꿀 필요 없이 기존 특성 그룹에서도 지원된다. 따라서 API 호출 코드를 바꾸기 전에 온라인 저장소 활성화 여부와 실제 StorageType을 확인해야 한다.
기존 Standard 그룹에는 두 가지 전환 경로가 제시됐다. Feature Processor로 레코드를 읽어 새 Standard_V2 그룹에 다시 적재하면 원본 그룹을 남겨 되돌릴 수 있지만, 전체 데이터의 읽기·쓰기 비용과 클라이언트의 대상 그룹 변경이 따른다.
다른 방법은 UpdateFeatureGroup으로 기존 그룹의 StorageType을 Standard_V2로 전환하는 것이다. 이 방식은 그룹 이름과 API 엔드포인트를 유지하며, 이후 PutRecord나 BatchWriteRecord가 호출된 레코드부터 내부 형식이 바뀐다. 서비스 중단 없이 진행할 수 있지만 전환은 되돌릴 수 없고, 다시 쓰이지 않은 레코드는 기존 형식으로 남을 수 있다.
결국 읽기 단계를 없앨 수 있는 범위는 분명하다. 레코드가 온라인 저장소에 이미 있고, 그룹이 Standard_V2 또는 InMemory를 사용하며, 변경 대상이 호출당 100개 이하이고, EventTime과 TTL 조건을 충족하는 기존 레코드 수정 흐름이다. 신규 레코드 생성, 기존 Standard 형식의 미전환 데이터, 오래된 이벤트 처리에는 PutRecord나 별도의 마이그레이션·충돌 처리 로직이 계속 필요하다.
뉴스레터 구독
최신 Web3, AI, 암호화폐 뉴스를 이메일로 받아보세요.