ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 리팩터는 출력이 같을 때만 리팩터다
    AI Agent 2026. 8. 8. 09:00
    728x90
    반응형

    코드를 정리했는데 API 응답 순서가 바뀌었습니다.

    처음엔 별일 아니라고 생각했습니다.
    같은 항목들이 들어 있었으니까요.
    중복도 없고, 누락도 없고, 테스트도 통과했습니다.

    근데 화면은 달라졌습니다.

    사용자는 항목의 존재만 보는 게 아니라 순서도 보고 있었습니다.
    제가 “구조 정리”라고 부른 작업이 소비자 입장에서는 동작 변경이었습니다.

    그날 이후 리팩터를 보는 기준이 조금 차가워졌습니다.

    깨끗한 코드가 같은 동작을 보장하지 않았습니다

    리팩터는 기분이 좋습니다.

    긴 파일을 나누고, 중복 helper를 합치고, facade를 정리하면 코드가 읽히기 시작합니다.
    그래서 위험합니다.
    읽기 좋아졌다는 감각이 동작 보존을 대신하기 쉽습니다.

    제가 헛짚은 지점은 단일 조회를 배치 helper로 바꾸는 작업이었습니다.

    단일 조회는 내부적으로 최신순을 보장했습니다.
    배치 helper는 ID순으로 반환했습니다.
    둘 다 같은 데이터를 반환합니다.
    하지만 소비자에게는 다른 응답입니다.

    테스트가 못 잡은 이유도 단순했습니다.

    테스트가 “같은 항목이 있는가”만 봤고, “같은 순서인가”를 안 봤습니다.

    리팩터와 버그 수정을 섞으면 설명이 꼬였습니다

    또 다른 함정은 “어차피 정리하는 김에”였습니다.

    리팩터하다가 진짜 버그를 발견합니다.
    고치고 싶습니다.
    고치는 게 맞는 경우도 많습니다.
    문제는 그걸 같은 변경에 섞으면 나중에 무엇이 의도였는지 모릅니다.

    출력이 바뀌었을 때 리뷰어가 묻습니다.

    이건 정리의 부수효과인가요, 의도한 버그 수정인가요?

    대답이 흐리면 위험합니다.

    지금은 이렇게 나눕니다.

    Commit A: 구조만 정리, 출력 동일성 증명
    Commit B: 의도한 출력 변경, 버그 수정으로 문서화
    

    항상 커밋을 물리적으로 나누지는 못해도, 적어도 보고서에서는 나눕니다.
    “이 변경은 출력 보존”, “이 변경은 출력 변경”을 분리합니다.

    before/after 출력 비교가 제일 솔직했습니다

    리팩터 검증에서 제일 믿을 만한 건 소비자 관점 출력 비교였습니다.

    함수 내부가 어떻게 바뀌었는지는 덜 중요했습니다.
    같은 입력, 같은 계정, 같은 조건에서 응답이 같은지 봤습니다.
    특히 순서, null 처리, 기본값, 에러 코드, 권한 필드는 따로 봤습니다.

    status code
    top-level keys
    array ordering
    null vs missing
    default value
    error code/message
    

    이 목록은 화려하지 않습니다.
    하지만 실제로 많이 막아줬습니다.

    리팩터는 “테스트가 통과했는가”보다 “소비자가 같은 세계를 보았는가”가 더 중요했습니다.

    좋은 리팩터는 티가 덜 났습니다

    예전에는 큰 리팩터가 멋있어 보였습니다.
    파일 수가 줄고, 구조도가 깔끔해지고, 중복이 사라지면 뭔가 큰일을 한 느낌이 났습니다.

    요즘은 반대로 봅니다.

    좋은 리팩터는 소비자가 눈치채지 못합니다.
    로그도 조용하고, 화면도 같고, API도 같습니다.
    개발자만 내부에서 숨통이 트입니다.

    출력이 바뀌었다면 그건 리팩터가 아닐 수 있습니다.
    버그 수정이거나, 계약 변경이거나, 마이그레이션입니다.
    이름을 정확히 붙여야 합니다.

    이름이 정확하면 검증도 정확해집니다.

    다음에 큰 정리를 하게 되면 저는 먼저 출력 샘플부터 저장할 겁니다.

    코드를 열기 전에요.

    728x90
    반응형
Designed by Tistory.