SMAIVNN
article thumbnail

 

 

프로젝트 시작 전, 기존 몽고DB로 생성되었던 boilerPlate 코드를 TypeORM과 RDB로 변경하는 작업을 진행하고 있습니다. 또한 추가적으로 기본적인 Auth 관련 코드를 작성중입니다.

 

오늘은 서비스에서 회원 탈퇴시 고려할만한 사항들과 구현에 대해서 알아보고자 합니다.

 

회원 탈퇴 정책

회원 탈퇴는 우선 '개인정보 보호법'을 준수하는게 우선입니다. 하지만 이 글에서는 개인정보 보호법과 관련 내용은 다루지 않고 서비스 운영에서 회원의 탈퇴시 고려할 상황에 관해 알아보겠습니다.

자원 보유 검토

네이버 페이
네이버 쿠키

사용자가 서비스에서 갖고있는 포인트 / 주문 내역 등 여러가지 자원에 대해서 인지하고 있는지, 이에 대한 삭제를 인지하고 있는지 등을 검토해야합니다. 

 

서비스 측에서도 이러한 자원이 필수적이라면 탈퇴 불가 처리를 진행하도록 합니다.

 

탈퇴자 확인과 softDelete 구현

모바일 서비스의 경우 타인의 핸드폰을 통해 탈퇴 처리를 할 수 있습니다. 이를 방지하기 위해 비밀번호 / 핸드폰 인증 등 다양한 방법으로 본인임을 확인하여야 합니다.

 

아래는 간단한 비밀번호 확인 코드입니다.

// service
async deactivateUser(request, id: string, body: UserDeactiveDto) {
    const { user } = request;
    const { password, deleteReason } = body;
    if (user.id !== id) {
      throw new Error('different user');
    }

    try {
      const isPasswordMatching = bcrypt.compare(password, user.password);
      if (!isPasswordMatching) {
        throw new UnauthorizedException('password not matching');
      }
      await this.userRepository.deactivateUser(user, deleteReason);
    } catch (error) {
      throw new Error('Failed to deactivate user');
    }
  }
  
  //repository
  async deactivateUser(user: UserEntity, deleteReason: string) {
    try {
      user.deleteReason = deleteReason;
      user.deletedAt = new Date();
      user.is_deleted = true; // 또는, await this.userRepository.softDelete(id);를 진행해도 됩니다.
 
      await this.userDbAccess.save(user);
    } catch (error) {
      throw new Error('Failed to deactivate user');
    }
  }

 

passport를 통해 user객체가 넘어오면, 해당 객체의 비밀번호를 bcrypt를 통해 유저가 입력한 비밀번호와 검증합니다.

통과할경우 User entity의 is_delete 필드를 true처리합니다.

 

이때, DB의 데이터를 삭제하는 방식 중 논리적 삭제와 물리적 삭제가 있습니다.


물리적 삭제 : 실제로 데이터를 삭제합니다.
논리적 삭제 : 필드를 통해서 필터링합니다. is_del와 같은 필드를 true로 설정합니다. soft-delete라고도 불립니다.

 

 

TypoORM에서는 논리적 삭제를 위한 데코레이터를 제공해줍니다.

// Soft Delete : 기존에는 null, 삭제시에 timestamp를 찍는다.
  @Exclude()
  @DeleteDateColumn({ type: 'timestamptz' })
  deletedAt?: Date | null;

 

@DeleteDateColumn 데코레이터는 논리적 삭제를 하게 해줍니다.

이 데코레이터는 만약 해당 필드(예시 deletedAt)가 null이 아닐경우 find, findOne과 같은 조회 쿼리 실행 시 해당 데이터는 제외하고 조회합니다.

 

 

현재 유저는 3명이 있지만 1명은 탈퇴를 한 상황입니다.

 

이 때 전체 유저를 조회하는 쿼리를 진행할경우

이렇게 두개의 데이터만 조회됩니다.

 

마찬가지로 이를 사용하면 자연스럽게 로그인시 진행되는 findOne() 또한 조회되지 않습니다. 따라서 로그인도 막히게 됩니다.

 

만약 soft-delete된 행도 조회하고자 한다면 withDeleted:true 옵션을 사용하면 조회할 수 있습니다.

 

탈퇴 후 정책과 탈퇴 이유

사용자의 사이트 탈퇴 후 진행되는 정책에 대해서도 고지합니다.

예를들어 다음과 같은 정책이 있을 수 있습니다.

 

- 탈퇴 후 N시간 이내 재가입 원칙

- 탈퇴 후 사용자의 데이터 유지 원칙(게시글은 삭제되지 않음, 사용자 정보는 30일 뒤 삭제)

- 복원 불가 원칙

등등

 

특히 게시글의 경우 사용자가 탈퇴하더라도 남아있는 것이 서비스 입장에서는 긍정적일 것입니다.

 

마지막으로, 유저가 서비스를 탈퇴하려는 이유를 받을 수 있습니다.

  @ApiProperty({ description: '탈퇴 이유' })
  @Column({ type: 'text', nullable: true })
  deleteReason?: string;

서비스를 탈퇴하는 이유를 확실하게 하여 서비스의 품질을 향상시킬 수 있습니다.

 


 

초기 스타트업의 경우 사용자의 가입과 이용이 많이 중요한 만큼, 탈퇴하는 사용자가 없도록 방지하는 것이 중요합니다.

profile

SMAIVNN

@SMAIVNN

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!