← 전체 글로 돌아가기

웹 개발

데이터가 사라졌을 때 대응

사용자가 만든 데이터가 갑자기 없어졌거나 다른 값으로 바뀌었다면, 삭제 로직, 캐시, 또는 동시성 문제를 의심해야 합니다.

사용자가 "저장한 데이터가 없어졌다"고 한다. 또는 "어제 저장한 것과 다르다"고 한다. 운영 중이라면 침착하게 진단해야 한다.

먼저 현재 상태 파악

데이터가 정말 없는가, 아니면 조회가 안 되는 건가?

# 데이터베이스에 직접 접근
psql -U postgres -d mydb

SELECT * FROM items WHERE user_id = 123 ORDER BY created_at DESC;

데이터베이스에 있으면 조회 로직이 잘못된 것. 없으면 데이터가 정말 삭제됐다.

삭제 로그 확인

update나 delete 쿼리가 실행됐는가?

# 데이터베이스 로그
grep DELETE /var/log/mysql/query.log | tail -20

# 또는 애플리케이션 로그
grep "delete\|destroy\|remove" /var/log/myapp.log

의도하지 않은 삭제 쿼리가 있는가? 예:

DELETE FROM items; -- WHERE 조건이 없다!

삭제 권한 확인

누가 이 데이터를 지웠나?

# 데이터베이스 감사 로그 (PostgreSQL)
SELECT * FROM pgaudit.audit_log WHERE object_name = 'items' ORDER BY timestamp DESC;

# 또는 애플리케이션 로그에서 사용자 ID 추적
grep "user_id=123" /var/log/myapp.log | grep "delete"

사용자 자신이 지웠을 수도, 관리자가 지웠을 수도, 버그로 지워졌을 수도 있다.

동시성 문제

여러 사용자가 같은 데이터를 동시에 수정하면서 충돌이 난 건 아닐까?

-- 데이터의 버전 확인
SELECT id, user_id, content, version, updated_at FROM items WHERE id = 456;

Version이 계속 증가했으면 여러 번 업데이트된 것. 마지막 업데이트가 이전 것을 덮어썼을 수 있다.

트랜잭션 롤백

DB 트랜잭션이 롤백되면서 변경사항이 사라졌을 수 있다.

// 나쁜 예: 에러 후 롤백
async function saveData(data) {
  const trx = await db.transaction();

  try {
    await trx('items').insert(data);
    await trx('logs').insert({ user_id: userId, action: 'create' });
    // 뭔가 에러
    throw new Error('문제 발생');
    await trx.commit();
  } catch (err) {
    await trx.rollback(); // 모든 변경 취소!
    throw err;
  }
}

캐시 불일치

데이터는 있는데 캐시에서만 없을 수 있다.

// 나쁜 예: 삭제 후 캐시를 안 지운다
await deleteItem(id);
// 캐시는 여전히 옛날 데이터를 반환한다

// 낫다: 삭제 후 캐시도 무효화
await deleteItem(id);
await cache.del(`item:${id}`);
await cache.del('items:list'); // 목록도 갱신

소프트 삭제 확인

실제로 삭제하지 않고 deleted_at 플래그만 설정하는 경우가 있다.

-- 데이터가 soft delete되지 않았나?
SELECT * FROM items WHERE user_id = 123 AND deleted_at IS NOT NULL ORDER BY deleted_at DESC;

Deleted_at이 있으면 의도적으로 숨긴 것. 복구하려면 deleted_at을 null로 설정한다.

UPDATE items SET deleted_at = NULL WHERE id = 456;

복구 계획

Data가 정말 사라졌다면:

  1. 데이터베이스 백업에서 복구 가능한가?
  2. 몇 시간 전 백업이 있는가?
  3. 트랜잭션 로그에서 복구할 수 있는가?
# 최근 백업 확인
ls -la /backup/database/

# 특정 시점으로 복구
psql -U postgres mydb < /backup/database/mydb_20240630_0200.sql

최종 확인: 원인 파악 및 예방

  1. 데이터가 언제 사라졌는가? (타임스탐프)
  2. 누가 작업했는가? (User ID, IP)
  3. 의도한 삭제인가, 버그인가?
  4. 다른 사용자에게도 영향을 미쳤는가?

운영 중에는 데이터 변경 로그를 항상 기록해야 한다. 그래야 문제가 생겼을 때 원인을 추적할 수 있다.