본문 바로가기
(개발) 프로젝트/tis-labs : 채용공고 수집 및 전시

페이지 방문 기반 사용자 식별 : 일회성 고유 ID 생성과 사용자 행동 데이터 수집

by yuiee 2025. 3. 17.

상황 : 사용자 로그인 없이 사용자 행동 데이터 수집 필요

프로젝트를 진행하며 사용자의 행동 데이터를 수집해야 했습니다. 각 사용자가 페이지를 언제 방문하며, 평균적으로 몇개의 공고를 보는지에 대한 데이터를 수집하여 서비스를 개선하고자 했기 때문입니다. 이때, 사용자가 채용공고들을 조회하고 관심있는 채용공고를 클릭하는데 있어 로그인을 강제하는 것은 사용자 경험을 저하시킨다고 판단했습니다. 그래서 사용자 로그인 없이 사용자를 식별하고 행동데이터를 수집할 수 있는 시스템이 필요했습니다.

 

 

문제

사용자 인증 없는 환경에서 사용자를 식별하기 위해 아래 세가지 이슈를 검토해야 했습니다.

  1. 사용자 식별 기준 설정 : 각 페이지 방문마다 새로운 사용자로 볼 것인지 VS 일정 시간 동안의 방문을 동일 사용자로 볼것인지
  2. 사용자 식별 ID 생성 방식 : UUID v4 VS UUID v1 VS Snowflake ID
  3. 사용자 식별 ID 저장 위치 : 서버 측 세션, 클라이언트 측 세션 스토리지, 쿠키 중 어떤 방식을 사용할 것인지

 

 

해결 

1. 사용자 식별 기준 설정
사용자 식별 기준은 각 페이지 방문마다 새로운 사용자로 보는 것으로 결정했습니다. 그 이유는 각 페이지 방문마다 새로운 사용자로 보는 방식이 단순하고 프로젝트 목표가 각 페이지 방문에서의 상호작용 분석에 초점이 맞춰져 있었기 때문입니다.

 

2. 사용자 고유 ID 생성 방식 비교
Snowflake ID를 선택했습니다. 그 이유는 Snowflake ID는 64bit 정수형으로 128 bit인 UUID에 비해 저장 및 전송 시 더 적은 용량을 차지하고, 타임스탬프와 노드 정보를 나타내는 bit가 할당되어 중복을 방지하고 시간 순 정렬이 가능했기 때문입니다.

@Configuration
public class SnowflakeConfig {
    @Value("${snowflake.node-id}")
    private int nodeId;

    @Bean
    TsidFactory tsidFactory() {
        if (nodeId < 0 || nodeId > 1023) {
            throw new IllegalArgumentException("nodeId must be between 0 and 1023");
        }
        return new TsidFactory(nodeId);
    }
}

 

 

@Component
@RequiredArgsConstructor
public class UserIdMaker {
    private final TsidFactory tsidFactory;

    public Long generate() {
        return tsidFactory.create().toLong();
    }
}

 

3. 사용자 식별 ID 저장 위치
클라이언트 측 세션 스토리지를 선택했습니다. 그 이유는 서버에서 데이터를 저장할 인프라를 관리하지 않아도 되고, 관리 지점이 줄어들기 때문입니다. 아이디 생성방식을 통해 중복가능성이 거의 없기에 서버에서 추가적인 중복 검증이 필요하지 않기 때문입니다. 또한 쿠키와 달리 모든 HTTP 요청에 포함시키지 않아도 되기에 필요할 때만 전송할 수 있어 불필요한 트래픽을 줄일 수 있었기 때문입니다.

export const USER_ID_KEY = 'JOB_BOARD_USER_ID';

export async function handleCardClick(event) {
   const userId = sessionStorage.getItem(USER_ID_KEY);
   const response = await fetch(`/api/v1/jobs/${jobId}/view`, {
       method: "POST",
       headers: { 'Content-Type': 'application/json' },
       body: JSON.stringify({ id: userId, viewCount: viewCount })
   });
}

 

결과

Snowflake ID 사용으로 UUID 대비 저장공간을 50% 절약할 수 있었고, 클라이언트 측 세션 스토리지 활용으로 서버 메모리 사용량을 줄일 수 있었습니다. 또한 이러한 과정을 통해 사용자가 페이지 방문시 평균적으로 몇개의 공고를 조회하는지, 어느 시간대에 방문하는지의 데이터를 수집할 수 있게 되었고, 의사결정의 기반을 마련할 수 있었습니다.

댓글