ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Deep Dive] Spring WebFlux와 Optimistic UI: 기술적 한계를 넘어선 성능 최적화
    면접 준비/포트폴리오 2026. 2. 26. 14:29

    프로젝트  개발하며 단순히 기능을 구현하는 것에 그치지 않고, 선택한 기술이 가진 트레이드 오프(Trade-off)를 고민하고 문제를 해결했던 과정을 기록합니다.


    1. Spring WebFlux: 고성능을 위한 선택과 그 이면

    주식 데이터와 AI 응답을 처리하기 위해 Spring WebFlux를 도입했습니다. 적은 스레드로 대량의 요청을 처리할 수 있다는 장점이 있었지만, 실제 적용 과정에서 마주한 단점과 극복 방안을 공유합니다.

    ⚠️ 마주한 한계점

    • 디버깅의 복잡성: 비동기 논블로킹 방식으로 동작하다 보니, 에러 발생 시 스택 트레이스(Stack Trace)가 여러 스레드에 걸쳐 있어 원인을 한눈에 파악하기 어려웠습니다.
    • 학습 곡선: 명령형(Imperative) 방식에 익숙했던 팀원들에게 Mono와 Flux 연산자는 코드 가독성을 떨어뜨리는 요인이 되기도 했습니다.

    💡 해결 전략

    • log() 연산자와 checkpoint()를 활용하여 데이터 흐름의 단계를 기록함으로써 디버깅 효율을 높였습니다.
    • 모든 로직을 WebFlux로 짜기보다, CPU 연산이 집중되는 부분과 I/O가 집중되는 부분을 분리하여 자원을 효율적으로 배분했습니다.

    2. Race Condition 제어: DB 제약 조건을 활용한 정합성 확보

    사용자가 관심 종목 버튼을 빠르게 여러 번 클릭할 경우, 동일한 데이터가 중복으로 저장되는 경쟁 상태(Race Condition) 문제가 발생할 수 있었습니다.

    🛠️ 구현 코드: 예외 핸들링을 통한 제어

    단순히 서버 코드에서 체크하는 방식은 동시 요청 시 뚫릴 위험이 있어, DB 유니크 제약 조건을 최종 수비수로 활용했습니다.

    @Transactional
    public Mono<Void> addWatchlist(WatchlistRequest request) {
        return watchlistRepository.save(new Watchlist(request.getUserId(), request.getStockCode()))
                .onErrorResume(DataIntegrityViolationException.class, e -> {
                    // 중복 데이터 인입 시 사용자에게 친절한 에러 메시지 반환
                    return Mono.error(new AlreadyExistsException("이미 등록된 종목입니다."));
                })
                .then();
    }
    

    📚 Tech Dictionary: 경쟁 상태(Race Condition) 두 개 이상의 프로세스가 공통 자원에 동시에 접근하여 결과값이 달라지는 현상입니다. 저는 이를 방지하기 위해 DB 레벨의 Unique Index를 설정하고 예외를 캐치하는 방식을 택했습니다.


    3. 데이터 정합성 유지: 로컬과 서버의 싱크(Sync) 맞추기

    낙관적 UI(Optimistic UI)를 구현하면서, 로컬 스토리지에 먼저 데이터를 쓰고 서버 호출에 실패했을 때의 데이터 불일치 문제를 해결해야 했습니다.

    🔄 Dual-Write와 보상 트랜잭션

    서버 API 호출이 실패했을 때, 사용자가 보는 화면(로컬 데이터)을 이전 상태로 되돌리는 '롤백(Rollback)' 로직을 프론트엔드에 구현했습니다.

    1. UI 업데이트: 버튼 클릭 즉시 로컬 스토리지 업데이트 및 화면 반영.
    2. API 호출: 백엔드 서버로 데이터 전송.
    3. 예외 처리: API 실패 시 catch 블록에서 로컬 스토리지를 이전 상태로 복구(Compensation)하고 에러 메시지 노출.

    4. 마치며: '왜?'라는 질문에 답하는 개발

    이번 프로젝트를 통해 기술은 단순히 유행을 따르는 것이 아니라, 서비스의 특성과 제약 사항에 맞춰 선택해야 함을 깨달았습니다.

    • WebFlux는 응답성을 높여주었지만 디버깅 비용을 요구했고,
    • Optimistic UI는 체감 속도를 높여주었지만 정합성 관리라는 숙제를 던져주었습니다.

    이러한 고민의 과정들이 모여 더 견고한 서비스를 만드는 밑거름이 되었다고 생각합니다. 앞으로도 기술의 명암을 동시에 살피는 개발자로 성장하겠습니다.

Designed by Tistory.