Dandy Now!
  • 웹 애플리케이션 유저 삭제: 물리적 삭제와 논리적 삭제
    2025년 08월 26일 16시 36분 39초에 업로드 된 글입니다.
    작성자: DandyNow
    728x90
    반응형

    웹 애플리케이션 유저 삭제: 물리적 삭제와 논리적 삭제

    1. 유저 계정 삭제의 두가지 방식

    웹 애플리케이션의 세계에서 사용자의 흔적을 지우는 방법은 마치 오래된 앨범에서 사진을 꺼내듯 신중해야 한다. 사용자가 서비스를 떠날 때, 우리는 두 가지 갈림길에 서게 된다. 하나는 모든 기록을 깨끗하게 지워 흔적조차 남기지 않는 물리적 삭제의 길이고, 다른 하나는 겉으로는 보이지 않게 숨겨두어 필요에 따라 다시 꺼내볼 수 있도록 하는 논리적 삭제의 길이다. 이 두 방식은 각각 고유한 의미와 결과를 낳기에, 개발자는 깊은 고민 끝에 하나의 길을 선택해야 한다.

    • 물리적 삭제는 단호한 종결을 의미한다. 마치 강물에 던져진 돌멩이처럼, 한 번 사라지면 그 존재를 다시 찾을 수 없다. 이는 때로는 사용자의 완벽한 망각을 보장하지만, 예기치 않은 상황에서의 후회를 남길 수도 있다.
    • 논리적 삭제는 여백을 남기는 행위와 같다. 이야기는 잠시 멈췄지만, 완전히 끝난 것은 아니다. 언젠가 다시 돌아올 수도 있고, 남겨진 흔적은 서비스 운영에 필요한 중요한 단서가 될 수도 있다.

    2. 물리적 삭제 (Physical Deletion)

    물리적 삭제는 데이터베이스의 해당 사용자 레코드를 완전히 삭제하는 것을 의미한다. 이 방식은 사용자의 모든 정보(개인 정보, 게시물 등)를 데이터베이스에서 영구적으로 제거한다.

    특징

    • 데이터의 완전한 제거: 데이터베이스에서 사용자 정보가 완전히 사라지므로, 개인정보 보호 측면에서 유리할 수 있다.
    • 용량 절약: 삭제된 데이터가 차지하던 저장 공간이 회수되어 데이터베이스의 용량을 절약할 수 있다.
    • 복구 불가: 일단 삭제되면 데이터 복구가 불가능하다.
    • 참조 무결성 문제: 다른 테이블에서 삭제된 사용자를 참조하고 있을 경우, 참조 무결성(Referential Integrity) 문제가 발생할 수 있다. 예를 들어, 사용자가 작성한 게시물에 user_id가 남아있다면, 게시물 데이터가 '고아 데이터(orphan data)'가 되거나, JOIN 쿼리 시 오류가 발생할 수 있다.

    적용 사례

    • 법적으로 데이터 보관 의무가 없는 단순한 임시 데이터.
    • 개인정보 보호 정책에 따라 사용자의 모든 정보를 완전히 삭제해야 하는 경우.

    3. 논리적 삭제 (Logical Deletion)

    논리적 삭제는 실제 데이터는 그대로 두고, 사용자 레코드에 '삭제 여부'를 나타내는 상태 필드(예: is_deleted 또는 status)를 추가하여 그 값을 true나 'deleted'로 변경하는 방식이다. 데이터는 여전히 존재하지만, 애플리케이션에서는 해당 사용자가 삭제된 것으로 간주하고 더 이상 노출되지 않도록 처리한다.

    특징

    • 데이터 보존: 사용자 데이터가 데이터베이스에 계속 남아있으므로, 필요에 따라 복구가 가능하다.
    • 데이터 무결성 유지: 다른 테이블과의 참조 관계가 깨지지 않아 데이터의 일관성을 유지하기 쉽다. 예를 들어, 삭제된 사용자가 쓴 게시물은 계속 해당 사용자를 참조할 수 있다.
    • 용량 비효율성: 삭제된 데이터가 계속 데이터베이스 공간을 차지한다.
    • 쿼리 복잡성: 데이터를 조회할 때 항상 '삭제되지 않은' 레코드만 필터링하는 조건(WHERE is_deleted = false)을 추가해야 하므로 쿼리가 다소 복잡해질 수 있다.

    적용 사례

    • 사용자 데이터 복구 가능성이 있는 경우 (예: '탈퇴 후 30일 이내 재가입 시 복구').
    • 사용자가 작성한 게시물, 댓글 등 관련 데이터의 무결성을 유지해야 하는 경우.
    • 법적 또는 비즈니스 목적으로 일정 기간 사용자 데이터를 보관해야 하는 경우.

    4. 요약 및 선택 기준

    어떤 방식을 선택할지는 애플리케이션의 비즈니스 요구사항법적 규제에 따라 결정해야 한다.

    특징 물리적 삭제 논리적 삭제
    데이터 복구 불가능 가능
    데이터 무결성 위험 안전
    개인정보 보호 유리 불리
    저장 용량 절약 비효율적
    쿼리 복잡성 단순 복잡

    5. 하이브리드 방식: 두 방식의 조화

    때로는 하나의 방식만으로는 충분하지 않다. 물리적 삭제와 논리적 삭제의 장점을 취하고 단점을 보완하기 위해 하이브리드 방식을 고려할 수 있다. 예를 들어, 사용자가 탈퇴를 요청하면 먼저 논리적 삭제를 수행하여 일정 기간 동안 데이터를 보관하고, 그 기간이 지나면 물리적 삭제를 진행하는 것이다. 이는 사용자의 재가입 가능성을 열어두면서도, 궁극적으로는 데이터베이스를 효율적으로 관리하고 개인 정보 보호를 강화할 수 있는 방법이다.

    아래는 Node.js 환경에서 하이브리드 방식의 매우 단순한 예시이다.

    1. 데이터베이스 모델 (예: Sequelize 사용)
    • User 모델에 deletedAt 컬럼을 추가한다. 이는 삭제 시간을 기록하기 위한 컬럼으로, null이면 활성 상태, 삭제 시간이 기록되어 있다면 논리적으로 삭제된 상태를 의미한다.
    1. 사용자 삭제 API
    • 사용자가 삭제를 요청하면, deletedAt 컬럼에 현재 시간을 기록한다 (논리적 삭제).
    1. 일정 기간 후 물리적 삭제 스크립트
    • 주기적으로 실행되는 스크립트를 통해 deletedAt 값이 특정 기간(예: 30일) 이전인 사용자 데이터를 데이터베이스에서 완전히 삭제한다 (물리적 삭제).

    아래 코드는 위 시나리오를 가정한 예시이다.

    // 모델 정의 (Sequelize 예시)
    const { DataTypes, Sequelize } = require("sequelize");
    const sequelize = new Sequelize("sqlite::memory:"); // 예시를 위한 임시 DB
    
    const User = sequelize.define("User", {
      username: DataTypes.STRING,
      email: DataTypes.STRING,
      deletedAt: DataTypes.DATE,
    });
    
    // 논리적 삭제 API (가정)
    async function deleteUserLogic(userId) {
      const user = await User.findByPk(userId);
      if (user) {
        user.deletedAt = new Date();
        await user.save();
        console.log(`User ${userId} 논리적으로 삭제됨`);
      } else {
        console.log(`User ${userId} 를 찾을 수 없음`);
      }
    }
    
    // 물리적 삭제 스크립트 (일정 기간 후 실행)
    async function deleteUserPhysical(retentionDays = 30) {
      const cutoffDate = new Date();
      cutoffDate.setDate(cutoffDate.getDate() - retentionDays);
    
      const deletedUsers = await User.findAll({
        where: {
          deletedAt: { [Sequelize.Op.lt]: cutoffDate },
        },
      });
    
      for (const user of deletedUsers) {
        await user.destroy(); // 물리적 삭제
        console.log(`User ${user.id} 물리적으로 삭제됨`);
      }
    }
    
    // 예시 실행
    async function main() {
      await sequelize.sync();
    
      const newUser = await User.create({
        username: "testuser",
        email: "test@example.com",
      });
      console.log("새로운 유저 생성:", newUser.toJSON());
    
      await deleteUserLogic(newUser.id); // 논리적 삭제
    
      // 30일 후 (가정) 물리적 삭제 스크립트 실행
      // await deleteUserPhysical();
    }
    
    main();

    6. 결론

    유저 삭제 기능은 단순한 기술적 구현을 넘어, 사용자의 권리와 서비스의 정책, 그리고 데이터 관리의 효율성을 고려해야 하는 중요한 결정이다. 물리적 삭제와 논리적 삭제, 그리고 하이브리드 방식까지 다양한 선택지 앞에서, 개발자는 서비스의 특성과 요구사항을 깊이 이해하고 신중한 판단을 내려야 할 것이다. 사용자의 마지막 발자국이 머무는 곳까지, 깊은 고민과 배려가 필요하다.


    728x90
    반응형
    댓글