동시성 제어
Q. 동시에 여러 사용자가 같은 ID로 회원가입을 시도할 때 발생할 수 있는 문제점은 무엇이며, 어떻게 해결 할 수 있을까요?
동시에 여러 사용자가 같은 ID로 회원가입을 시도하는 상황에서는 Race Condition이 발생할 수 있습니다. 예를 들어, A와 B 사용자가 동시에 'user123'이라는 ID로 가입을 시도한다고 가정했을때, 두 사용자가 거의 동시에 ID 중복 체크를 하면, 둘 다 해당 ID가 존재하지 않는다고 판단하고 회원가입을 진행할 수 있습니다. 이런 경우 데이터 정합성이 깨질 수 있습니다. 이를 해결하기 위한 방법으로는 크게 세 가지를 고려할 수 있습니다. 첫째, 가장 쉬운 방법으로 데이터베이스 컬럼에 유니크 제약조건을 설정하는 방법입니다. ID 컬럼에 unique constraint를 걸어두면, 중복 데이터 삽입 시도 시 에러가 발생하여 하나의 회원만 가입되도록 보장할 수 있습니다. 두번째, 애플리케이션 레벨에서 ConcurrentHashMap을 사용하여 atomic한 처리를 할 수 있습니다. putIfAbsent() 메소드를 활용하면 체크와 등록을 원자적으로 수행할 수 있어서 안전합니다. 세번째, MSA같은 분산 환경에서는 Redis를 활용한 분산 락을 고려할 수 있습니다. 실제 프로젝트에서는 이러한 방법들을 상황에 맞게 조합하여 사용하는 것이 좋습니다. 저는 주로 데이터베이스의 유니크 제약조건을 기본으로 하고, 추가적인 안정장치로 애플리케이션 레벨에 ConcurrnetHashMap을 구현하는 방식을 선호합니다.
Q. ConcurrnetHashMap에 대해 조금 더 자세히 설명해주세요.
ConcurrentHashMap은 Java 5부터 도입된 동시성 컬렉션입니다. 기존 HashMap은 멀티스레드 환경에서 synchronized 키워드를 사용해 동기화를 하는 방식을 사용했었습니다. 이는 Map 전체에 락을 걸어 성능이 좋지 않았습니다. ConcurrentHashMap의 핵심은 분할 잠금(Segmentation)으로 전체 Map을 여러 세그먼트로 나누고, 각 세그먼트별로 락을 걸어 동시성을 향상시켰습니다. Java 8부터는 이 방식이 개선되어 Node 단위의 더 세밀한 락킹을 사용합니다. 여러 노드들도 나누어져 있어 락을 걸지 않아도 높은 동시성과 성능을 보장하면서도 스레디 안전성을 제공해 안정적인 데이터 업데이트가 가능합니다.
Last updated