7 분 소요

13단계 else-if 사다리를 순수 함수로 바꾸던 날

개발 회고 — 2026-07-20 (월)

오늘 작업 요약

두 갈래로 작업이 진행됐다. 한쪽에서는 분할 화면(SplitView)의 접기 레이아웃 로직을 분석해 순수 함수로 리팩토링하고, 그 과정에서 발견한 외부 참조 컬럼 조회 버그를 함께 수정했다. 다른 쪽(별도 브랜치)에서는 캘린더 이벤트 정렬과 타임존 이중 보정 문제를 근본 원인부터 해결했다.

세션 1 — SplitView 접기 로직 리팩토링

  • 접기 상태를 판정하는 여러 헬퍼 함수와, 화면 분할 비율/크기를 계산하는 13단계짜리 조건 분기를 순수 함수로 분리
  • 중복된 프레임 조회 로직, 디버그용 로그, 하드코딩된 디버그 값 제거
  • TDD 방식으로 계산 로직을 별도 파일로 추출하고, 캐릭터라이제이션 테스트 33개로 기존 동작을 고정
  • 외부 참조 컬럼 데이터의 폭이 헤더 폭보다 좁을 때 값이 undefined가 되던 버그 수정
  • 이번 작업과 무관한 파일들을 커밋에서 분리하고, 죽은 코드와 불명확한 변수명을 정리

세션 2 — 캘린더 이벤트 정렬 및 타임존 수정

  • “더보기” 팝오버에서 이벤트를 멀티데이 > 종일 > 시간 지정 순으로 정렬하는 로직 구현
  • 종료 시간이 시작 시간과 같은(0분) 이벤트를 캘린더 라이브러리의 개념에 맞게 근본적으로 해결
  • 새 일정 생성 시 발생하던 타임존 이중 보정 문제 2건 해결
  • 새 일정 생성 시 클릭 종류에 따라 종료값을 자동으로 채우는 로직 추가
  • 월뷰 이벤트 시간/일수 표기 추가 및 더보기 팝오버 디자인 통일

STAR 정리

Situation (상황)

분할 화면의 접기/펼치기 상태를 판정하고 화면 크기를 계산하는 로직이 프레임 트리 깊이, 분할 방향, 형제 프레임 상태를 동시에 고려해야 해서 13단계짜리 조건 분기로 얽혀 있었다. 이 로직은 렌더링 코드와 상태 읽기가 섞여 있어 직접 테스트하기 어려운 구조였다. 한편 외부 참조 컬럼 데이터를 조회하는 과정에서, 응답 데이터의 폭이 헤더 정의보다 좁을 때 값이 undefined가 되는 버그도 있었다. 별도로 진행하던 캘린더 작업에서는, 종료 시간이 시작 시간과 같은 이벤트를 표시할 때 여러 곳에 흩어진 보정 코드로 임시 처리하고 있었고, 새 일정을 생성할 때 타임존이 두 번 보정되어 값이 어긋나는 문제가 있었다.

Task (과제)

  1. 접기 레이아웃 판정 로직을 테스트 가능한 순수 함수로 분리
  2. 형제 프레임을 찾는 중복 로직을 하나로 통합
  3. 외부 참조 컬럼 데이터의 폭 불일치를 방어하는 로직 추가
  4. 더보기 팝오버의 이벤트 정렬 우선순위를 명확히 정의
  5. 0분 이벤트 문제를 근본 원인 수준에서 해결
  6. 타임존 보정이 여러 곳에서 중복 적용되지 않도록 단일화

Action (행동)

  • 접기 상태를 판정하는 여러 헬퍼 함수와, 화면 분할 시 필요한 크기 계산 사다리를 분석해 계산 로직만 별도 파일로 뽑아냄. 입력값(프레임과 부모 상태)과 출력값(크기, 렌더링 여부 플래그)을 명확히 분리한 순수 함수로 정의하고, 그 동작을 고정하는 캐릭터라이제이션 테스트를 33개 작성함
  • 중복 프레임 조회 로직, 디버그용 로그, 하드코딩된 디버그 값 등 불필요한 코드를 제거하고, 여러 곳에 흩어져 있던 “형제 프레임 찾기” 로직을 하나의 헬퍼로 통합함. 통합 과정에서 각 사용처가 전제하던 “형제”의 정의가 모두 일관되는지 검증함
  • 외부 참조 컬럼 데이터에서, 실제 데이터 행의 폭이 헤더 정의보다 좁을 때 인덱스로 접근하면 값이 undefined가 되는 문제를 발견하고, 폭이 부족하면 첫 번째 값을 대신 사용하는 방어 로직을 추가함. 다른 화면(그리드)에서 유사한 패턴이 있는지도 함께 점검해, 실제로는 도달 불가능한 죽은 코드였음을 확인함
  • 이번 작업과 무관한 파일들은 커밋에서 제외해 작업 트리에만 남겨두고, 죽은 기본 파라미터와 불명확한 변수명을 정리함
  • 더보기 팝오버에서 이벤트를 표시할 때, 멀티데이 이벤트를 가장 먼저, 그다음 종일 이벤트, 마지막으로 시간이 지정된 이벤트 순으로 정렬하는 우선순위 로직을 추가함
  • 종료 시간이 시작 시간과 같은 이벤트를, 캘린더 라이브러리가 갖고 있는 “종료 시간이 있는 이벤트인지” 개념을 제대로 활용하는 방식으로 재구성함. 기본 이벤트 길이를 최상위 설정값으로 옮기면서, 여기저기 흩어져 있던 보정 코드를 제거함
  • 새 일정을 생성할 때 발생하던 타임존 이중 보정 문제를, 값이 처음 만들어지는 지점 한 곳에서만 보정하도록 정리해 하위 계층의 중복 보정 코드를 제거함
  • 새 일정 생성 시 클릭한 방식에 따라 다른 기본 종료값을 계산해 자동으로 채우는 로직을 추가함
  • 월뷰 이벤트에 시간/일수 표기를 추가하고, 더보기 팝오버의 디자인을 통일하고, 일정 저장 시 종료 시간 검증 로직을 정비함

Result (결과)

  • 접기 레이아웃 계산 로직이 순수 함수로 분리되어, 이후 렌더링 코드를 수정할 때 테스트만으로 신뢰도 높게 리팩토링할 수 있는 기반이 마련됨
  • 외부 참조 컬럼 조회 버그가 방어 로직으로 수정됨. 폼 컴포넌트는 그리드의 공유 참조를 사용하는 구조라, 그리드 쪽 방어 로직이 폼에도 자동으로 적용됨을 확인함
  • 캘린더 쪽에서는 0분 이벤트, 타임존 이중 보정, 더보기 팝오버 정렬 문제가 모두 해결된 것으로 확인됨(작성 시점 기준 미해결 항목 없음)
  • 두 세션 모두 로컬 테스트와 E2E 테스트 실행은 다음 단계로 남아있음

실제 측정 가능한 지표

지표 확인 방법 비고
SplitView 리팩토링 커밋 규모 git show --stat 2개 커밋, 16개 파일(신규 2개, 기존 14개)
캐릭터라이제이션 테스트 개수 테스트 파일 내 it() 블록 수 33개
캘린더 세션 커밋 규모 git log --stat (calendar 브랜치) 21개 커밋, 18개 파일 변경
통합된 중복 로직 개수 리팩토링 전/후 “형제 찾기” 관련 코드 위치 수 비교 3곳 → 1곳으로 통합
제거된 보정 코드 개수 0분 이벤트 관련 수정 전/후 diff에서 제거된 보정 블록 수 드래그 처리, 과거 여부 판정, 시간 라벨 등
Cypress E2E 테스트 통과 여부 CI 실행 결과 두 세션 모두 다음 단계 항목으로 남음

추정 가능한 효과 (근거 포함)

  • 순수 함수 분리로 향후 리팩토링 신뢰도 향상 (추정): 계산 로직이 렌더링과 분리되면서, 이후 렌더링 코드를 수정할 때 계산 로직에 대한 회귀를 테스트만으로 확인할 수 있게 되었을 것으로 예상됨. 근거: 별도 파일로 분리된 순수 함수와 33개의 캐릭터라이제이션 테스트를 확인함. 실제 이후 리팩토링에서 얼마나 시간이 단축되는지는 다음에 유사 작업이 있을 때 비교해봐야 함
  • 타임존 보정 단일화로 유사 버그 재발 가능성 감소 (추정): 보정 지점을 하나로 모으면서, 이후 새로운 화면이나 흐름이 추가되어도 중복 보정으로 인한 오차가 재발할 가능성이 줄어들 것으로 예상됨. 근거: 여러 지점에 흩어져 있던 보정 코드가 한 곳으로 정리된 것을 확인함. 실제 재발 여부는 이후 유사 기능 추가 시 확인 가능함

더 측정하면 좋은 지표

  1. SplitView 렌더링 로직 리팩토링 시 실제 회귀 발생 빈도: 이후 render() 관련 수정이 있을 때, 순수 함수 분리 전/후로 회귀 버그 발생률 비교
  2. 외부 참조 컬럼 방어 로직의 실제 적용 범위: 그리드 외에 폼, 다른 화면에서도 유사한 폭 불일치가 발생하는지 전수 점검
  3. 캘린더 0분 이벤트 처리 개선 전/후 코드 복잡도: 제거된 보정 코드 라인 수와 남은 로직의 복잡도(사이클로매틱 복잡도 등) 비교
  4. 더보기 팝오버 정렬 로직의 사용자 인지 편의성: 실제 사용자 피드백이나 사용성 테스트로 정렬 순서의 체감 효과 확인
  5. 두 세션 모두 남아있는 E2E 테스트 실행 결과: 실제 통과 여부와 실패 시 원인 분석

오늘 배운 것

  • 데이터 배열이 헤더 정의와 항상 폭이 일치한다고 가정하면 안 된다는 것을 다시 확인함. 외부 참조 응답처럼 비표준 폭을 받을 수 있는 데이터는 인덱스 기반 접근이 안전하지 않을 수 있다는 점
  • 렌더링과 상태 읽기가 섞여 있는 코드는 직접 테스트하기 어렵지만, 계산 로직만 순수 함수로 분리하면 캐릭터라이제이션 테스트를 훨씬 쉽게 작성할 수 있다는 것을 실감함. 이후 렌더링 코드를 수정할 때도 테스트만 보고 신뢰도 높게 작업할 수 있다는 것을 확인함
  • 여러 조건을 동시에 봐야 하는 판정 로직은, 조건을 순서대로 나열하는 방식보다 “어떤 조건이 참이면 이것을 쓰겠다”는 의도를 먼저 함수 시그니처로 명시하고 구현하는 편이 훨씬 읽기 좋다는 것을 배움
  • 공유 참조 구조를 쓰는 컴포넌트는, 한쪽(그리드)의 방어 로직 개선이 다른 쪽(폼)에도 자동으로 전파된다는 것을 확인함
  • 캘린더 라이브러리가 이미 갖고 있는 개념(종료 시간이 있는 이벤트인지 여부)을 제대로 이해하고 활용하면, 여러 곳에 보정 코드를 두지 않고도 깔끔하게 처리할 수 있다는 것을 배움
  • 표시용으로 임시로 만든 값이 실제 저장/조회 값에 섞여 들어가면 여러 계층에서 보정이 필요해지므로, 이런 값은 별도의 설정값으로 분리해 관리하는 것이 유지보수에 유리하다는 것을 확인함
  • 값을 보정하는 지점을 하나(입력값이 처음 만들어지는 곳)로 모으는 원칙이, 하위 계층에서 중복 보정을 막는 데 효과적이라는 것을 다시 느낌

어려웠던 점 / 막힌 부분

  • 접기 바(collapse bar)의 렌더링 로직에서, 화면 크기 계산 13단계와 병합 바/제목 노출 판정이 얽혀 있어 어디까지가 무조건 실행되는 부분이고 어디부터 조건부인지 헷갈렸다. 함수의 입력값과 출력값을 명확히 분리하고 나서야 한 번에 정리됨
  • 형제 프레임을 찾는 로직이 세 곳에서 각각 조금씩 다른 상황(접힌 그룹 찾기, 병합 바 판정, 크기 계산)에 쓰이고 있어, 하나로 통합하면서 “형제”의 정의가 모든 곳에서 일관되게 적용되는지 검증하는 데 신경을 많이 씀
  • 외부 참조 컬럼 데이터의 폭이 왜 헤더 폭과 다를 수 있는지 원인을 찾는 과정에서, 처음엔 백엔드 문제로 의심했으나 실제로는 값을 조회하는 특정 함수는 이미 결과를 정규화하는 반면, 다른 경로는 원본 데이터를 그대로 받아오기 때문이라는 것을 확인함. 근본적으로는 정규화 책임을 더 상위 계층에서 맡아야 하지만, 우선은 방어 로직으로 처리함
  • 0분 이벤트 문제의 원인을 처음엔 이벤트 생성 로직의 시간 조작으로 의심했으나, 실제로는 캘린더 라이브러리 내부 구조와 공개 API의 분리 방식을 제대로 이해하지 못한 것이 원인이었음을 확인함
  • 타임존 보정이 여러 지점에 흩어져 있어, 이를 모두 찾아내는 데 품이 들었음
  • 시간 표시 위치(줄 안/아래)를 결정하는 조건이, 종료 시간이 없는 이벤트일 때 무조건 “아래 배치”로 가던 엣지 케이스를 뒤늦게 발견해 수정함

내일 하면 좋은 작업

  1. 유사한 데이터 조회 패턴을 다른 화면에서도 감사해 동일한 폭 불일치 위험이 있는지 확인
  2. 관련된 폼 draft 처리 커밋의 영향 범위를 외부 참조 컬럼 관점에서 재검토
  3. 접기 레이아웃 계산 로직의 추상화가 다른 분할 관련 컴포넌트에도 적용 가능한지 검토
  4. 오늘 작성한 커밋들의 로컬 테스트 확인(더보기 팝오버 정렬, 타임존 보정, 0분 이벤트 표시)
  5. Cypress E2E 테스트 실행 및 통과 확인
  6. 메인 개발 브랜치로의 병합 검토 또는 다음 캘린더 이슈 진행

한 줄 요약

오늘은 SplitView 접기 로직을 순수 함수로 정리하고 숨은 외부 참조 컬럼 버그를 방어하는 한편, 캘린더 이벤트 정렬과 타임존 이중 보정 문제를 근본 원인부터 해결한 하루였다.

댓글남기기