과제
월요일에 과제가 공개되었고, 주요 요구사항은 다음과 같았다.
❓ point 패키지의 TODO 와 테스트코드를 작성해 주세요.
- 포인트 API 구현 (충전, 사용, 조회, 내역 조회)
- 잔고가 부족할 경우, 포인트 사용 실패
- 동시에 여러 건의 포인트 충전, 이용 요청이 들어올 경우 순차적으로 처리
과제 요구사항 분석
요구사항을 다음과 같이 세부적으로 정리할 수 있었다.
- 포인트 기능 구현
- 포인트 충전, 사용, 조회, 내역 조회 기능 구현
- 포인트 사용 시 잔고 부족 예외 처리
- 포인트 충전 시 최대 잔고 제한 고려
- 동시성 처리
- 동일 유저에게 동시에 여러 요청이 들어오는 경우 데이터 정합성 보장
- 유저별로 요청을 직렬화하여 순차적으로 처리해야 함
- 테스트 코드 작성 (TDD 기반)
- 각 기능별 성공/실패 케이스 테스트
- 동시에 여러 요청이 들어오는 상황에 대한 통합테스트
과제 해결 과정
1. 동시성 문제 해결
이번 과제의 핵심은 동시성 처리였다.
여러 사용자가 동시에 포인트를 충전하거나 사용할 때 잔고가 꼬이지 않도록 보장해야 했는데,
특히 하나의 유저에 대한 요청은 순차적으로 처리되는 것이 중요했다.
Java에서 대표적인 동시성 제어 방법으로는 synchronized
와 ReentrantLock
이 있다.
각각의 특징을 비교하며 어떤 방식이 적절할지 고민했다.
방법 | 장점 | 단점 |
---|---|---|
synchronized |
간편하게 동기화 구현 가능 | 하나의 유저 자원을 사용할 때 다른 유저도 대기하게 됨 (병목 발생 가능) |
ReentrantLock |
유저별로 독립적인 락 제어 가능 | 구현이 다소 복잡함, 락 해제 실수 주의 필요 |
유저별로 독립적인 락을 관리하기 위해 ReentrantLock
과 ConcurrentHashMap
을 조합하여 구현했다.
ConcurrentHashMap<userId, ReentrantLock>
구조를 통해 유저 단위로 락을 관리- 한 유저에 대한 포인트 충전/사용 요청은 직렬 처리되지만, 서로 다른 유저는 동시에 접근 가능
2. TDD 기반 테스트 코드 작성
이번 과제에서 TDD를 처음 작성해 보았기 때문에 시행착오가 많았다.
우선은 PointService에 집중하여 테스트 코드를 작성했고, 가능한 모든 성공/실패 케이스를 커버하는 데 중점을 두었다.
Mock과 Stub에 대해서도 고민이 많았다.
단순히 응답만 비교하는 Stub보다는 예상값과 결과값을 비교하고 특정 메서드가 호출되었는 지까지 검증 가능한 Mock 객체를 사용하는 것이 바람직하다고 판단했다.
구분 | Stub | Mock |
---|---|---|
목적 | 고정된 응답 제공 | 행위(Behavior) 검증 |
특징 | 객체의 상태 테스트에 적합 | 메서드 호출 여부, 파라미터 등을 검증할 수 있어 유연함 |
사용 이유 | 단순 데이터 테스트 | 복잡한 로직 및 의존성 검증 필요 시 |
모든 테스트는 다음 단계에 초점을 맞춰 코드를 작성하였다.
- Given – 테스트 조건과 예상값 정의
- When – 테스트 대상 메서드 호출
- Then – 반환 결과 및 기대값 비교
- Verify – 실제로 메서드가 호출되었는지 검증 (Mock 사용)
동시성 테스트 시도
ExecutorService
를 활용하여 동시에 여러 스레드에서 충전/사용 요청을 시도- 테스트 코드에서도 유저별로 락이 잘 동작하는지 검증
- 예상대로 포인트의 누적 결과가 정확히 일치함을 확인함
이번 주에 배운 것
- 동시성 처리 기법
ReentrantLock
,ConcurrentHashMap
을 통한 사용자별 락 관리
- TDD 실전 적용
- 실패 → 성공 테스트 흐름을 통해 기능을 안정적으로 설계
- Mock 객체를 활용한 행위 기반 테스트
마무리
이번 과제는 단순한 CRUD 기능 구현을 넘어서, 서비스에서 자주 발생하는 동시성 문제를 어떻게 해결할 것인가에 대해 깊이 고민해 볼 수 있는 좋은 기회였다.
앞으로도 실전에서 활용 가능한 기술들을 중심으로, 문제를 해결하는 데 있어 "왜 이렇게 구현해야 하는가?"를 끊임없이 되묻는 것을 목표로 해야겠다.
'Etc > 항해 플러스 Lite 백엔드 코스' 카테고리의 다른 글
[항해 플러스 Lite 백엔드] 4주차 WIL #Redis기반 대기열 토큰 관리 (0) | 2025.06.15 |
---|---|
[항해 플러스 Lite 백엔드] 3주차 WIL #클린아키텍처 #레이어드아키텍처 (0) | 2025.06.08 |
[항해 플러스 Lite 백엔드] 2주차 WIL #시나리오 분석 #설계 (3) | 2025.05.30 |