Three at once.
1. Suspend sales and statusName stays '승인완료' (approved).
Whether it's actually selling lives on a separate endpoint's onSale and stock count. Approval state and sales state are different axes.
2. Deleted items still come back with statusName='상품삭제' (product deleted).
★ Don't judge deletion by presence. Read "it's in the list, so it's alive" and you reprocess things already gone. Two batches repeated the same work every 20–30 minutes on this misread.
3. Status strings share prefixes.
임시저장 (saved as draft) and 임시저장중 (saving as draft) both exist as distinct strings.
if status == '임시저장': # misses 임시저장중
if status.startswith('임시저장'): # this is the one
★ Before comparing status values with ==, dump every value that actually exists. Values not in the docs will show up.
Why this bites non-ASCII users
When statuses are human-readable strings in your own language rather than IN_REVIEW-style codes, the temptation is to treat them like codes. They aren't. They are prose, they get new variants without a changelog, and a suffix (중, roughly "-ing") turns one state into two. Enumerate them from live data, never from the docs.