pile·
백엔드·마켓컬리마켓컬리 Hello World·

잘못 작성된 람다 코드를 삭제하기까지의 여정

Optional.map 안의 긴 람다로 구독 유효성을 판정하던 코드를 읽기 쉬운 도메인 메서드로 바꾼 작은 리팩토링 사례다. 짝 프로그래밍으로 실제 조건을 먼저 문장으로 풀고, 상대적인 이름을 고친 뒤 null·상태·기간 검사를 작은 메서드로 캡슐화했다. 줄 수를 줄이는 것보다 동료가 조건을 순서대로 이해하고 변경할 수 있게 만드는 것이 목표다.

핵심 포인트
  • 기존 람다는 null 검사, 기간 타입, 만료일, 사용자 상태를 한 블록에서 처리해 의도를 파악하기 어려웠다.
  • isUsedOldSubscription이라는 이름은 실제로 검사하는 유효성을 드러내지 못하고 old라는 상대적 표현까지 포함했다.
  • 조건을 hasValidPeriod, hasValidExpireDate, isUsable, isNotExpired, isUserStatusNormal로 나눴다.
  • 유효하지 않은 입력은 빠르게 false를 반환하고 마지막에 핵심 비즈니스 조건을 AND로 결합했다.
  • After 코드가 더 길어도 도메인 지식이 적은 개발자가 메서드 이름만 따라가며 판단 흐름을 읽을 수 있다.
상세 정리
  • 원래 목적: 현재는 구매할 수 없는 과거 구독형 서비스를 회원이 여전히 사용할 수 있는지 판단하는 로직이었다.
  • 기존 구현: Optional.map의 람다 안에서 별도 null 검증을 호출하고 기간 타입이 N이 아닌지, 만료일이 미래인지, 회원 상태가 NORMAL인지 한 번에 계산했다.
  • 악취 진단: 변수와 메서드 이름이 의미를 설명하지 못했고, 하나의 람다가 여러 도메인 규칙을 표현했다. Optional 파이프라인도 자연스럽게 읽히지 않았다.
  • 규칙 명시: NORMAL 회원이어야 하고 기간 타입이 N이 아니며 만료일이 현재 이후여야 한다. 관련 필드 중 하나라도 null이면 false다.
  • 이름 변경: 레거시 여부가 아니라 유효성을 검사하므로 isUsedOldSubscription을 isValidSubscription으로 바꿨다.
  • 상대어 제거: old는 시간과 맥락에 따라 의미가 달라져 메서드 계약을 안정적으로 설명하지 못한다는 점도 변경 근거였다.
  • 필드 검증: 기간 타입과 만료일의 null 여부를 각각 hasValidPeriod와 hasValidExpireDate로 감쌌다.
  • 상태 메서드: 기간 타입 사용 가능 여부, 만료 여부, 회원 NORMAL 여부도 각각 이름 있는 boolean 메서드로 분리했다.
  • 캡슐화 효과: 필드의 유효 기준이 바뀌면 호출부의 전체 조건문이 아니라 해당 검증 메서드만 수정할 수 있다.
  • 흐름 재구성: 잘못된 기간과 만료일은 early return으로 끝내고, 남은 사용자 상태·사용 가능·미만료 조건만 마지막 반환식에서 결합했다.
  • 대안 형태: 팀 취향에 따라 모든 작은 predicate를 하나의 AND 식으로 연결할 수도 있음을 함께 제시했다.
  • 개선 결과: 각 조건을 머릿속에 보관할 필요가 줄고 빠른 반환으로 실패 지점을 순서대로 읽을 수 있게 됐다.
  • 교훈: 람다는 일회성 로직이라는 이유만으로 선택할 도구가 아니다. 가독성이 떨어지면 명시적인 메서드와 비교한 뒤 더 이해하기 쉬운 쪽을 골라야 한다.
왜 읽나Optional과 람다를 과도하게 압축한 Java 도메인 로직을 의도가 드러나는 이름과 작은 predicate로 풀어내는 기준을 얻을 수 있다.
마켓컬리
마켓컬리 Hello World 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 백엔드·github-engGitHub Engineering·

    조기 종료를 없애야 벡터화된다 — 메모리 속도 소스 코드 케이스 폴딩

    GitHub의 코드 검색 엔진 Blackbird는 480TB 이상의 소스 코드를 인덱싱하기 전 모든 바이트에 case folding을 적용한다. 이 글은 Rust로 구현한 case folding을 메모리 대역폭 한계(45+ GiB/s)까지 끌어올린 두 가지 반직관적 최적화를 상세히 다룬다. 핵심은 루프 조기 종료(break) 제거로 LLVM 벡터화를 유도하고, UTF-8을 디코딩하지 않고 바이트 공간 산술만으로 fold를 수행하는 것이다.

    #rust#unicode#simd+2
  2. 백엔드·여기어때 (GC컴퍼니)여기어때 (GC컴퍼니)·

    트랜잭션 스크립트에서 숙소 메타 + 가격 계산 모듈로 — 전시 아키텍처 개선기 (2/3)

    여기어때 전시개발팀이 숙소 상세(PDP) API를 해부한 결과, 코드상으로는 DB 호출 3번처럼 보이던 요청이 실제로는 MongoDB $lookup 체인으로 컬렉션을 19회 접근하는 구조였다. 이 트랜잭션 스크립트 방식의 핵심 문제는 "aggregation이 I/O를 가린다"는 점으로, 독립적인 쿼리 10개가 단일 파이프라인에 직렬화되어 병렬화 기회를 잃고, 가격 때문에 거의 안 바뀌는 이미지까지 매 요청마다 읽어야 하는 읽기 증폭이 발생했다. V3에서는 "조회 시점 조립"을 "쓰기 시점 사전 조립"으로 전환하고, 화면별로 복제되던 가격 계산 로직을 goodsprice 단일 모듈로 수렴했다. 4개 API(PLP/PDP/RDP/ILP)의 반복 마이그레이션은 Claude Code skill로 절차를 고정하고 쉐도잉 + 동일성 검증으로 안전망을 마련하는 방식으로 진행됐다.

    #architecture#migration#caching+2