[개발 회고] 13단계 else-if 사다리를 순수 함수로 바꾸던 날
13단계 else-if 사다리를 순수 함수로 바꾸던 날
개발 회고 — 2026-07-20 (월)
오늘 작업 요약
두 갈래로 작업이 진행됐다. 한쪽에서는 분할 화면(SplitView)의 접기 레이아웃 로직을 분석해 순수 함수로 리팩토링하고, 그 과정에서 발견한 외부 참조 컬럼 조회 버그를 함께 수정했다. 다른 쪽(별도 브랜치)에서는 캘린더 이벤트 정렬과 타임존 이중 보정 문제를 근본 원인부터 해결했다.
세션 1 — SplitView 접기 로직 리팩토링
- 접기 상태를 판정하는 여러 헬퍼 함수와, 화면 분할 비율/크기를 계산하는 13단계짜리 조건 분기를 순수 함수로 분리
- 중복된 프레임 조회 로직, 디버그용 로그, 하드코딩된 디버그 값 제거
- TDD 방식으로 계산 로직을 별도 파일로 추출하고, 캐릭터라이제이션 테스트 33개로 기존 동작을 고정
- 외부 참조 컬럼 데이터의 폭이 헤더 폭보다 좁을 때 값이 undefined가 되던 버그 수정
- 이번 작업과 무관한 파일들을 커밋에서 분리하고, 죽은 코드와 불명확한 변수명을 정리
세션 2 — 캘린더 이벤트 정렬 및 타임존 수정
- “더보기” 팝오버에서 이벤트를 멀티데이 > 종일 > 시간 지정 순으로 정렬하는 로직 구현
- 종료 시간이 시작 시간과 같은(0분) 이벤트를 캘린더 라이브러리의 개념에 맞게 근본적으로 해결
- 새 일정 생성 시 발생하던 타임존 이중 보정 문제 2건 해결
- 새 일정 생성 시 클릭 종류에 따라 종료값을 자동으로 채우는 로직 추가
- 월뷰 이벤트 시간/일수 표기 추가 및 더보기 팝오버 디자인 통일
STAR 정리
Situation (상황)
분할 화면의 접기/펼치기 상태를 판정하고 화면 크기를 계산하는 로직이 프레임 트리 깊이, 분할 방향, 형제 프레임 상태를 동시에 고려해야 해서 13단계짜리 조건 분기로 얽혀 있었다. 이 로직은 렌더링 코드와 상태 읽기가 섞여 있어 직접 테스트하기 어려운 구조였다. 한편 외부 참조 컬럼 데이터를 조회하는 과정에서, 응답 데이터의 폭이 헤더 정의보다 좁을 때 값이 undefined가 되는 버그도 있었다. 별도로 진행하던 캘린더 작업에서는, 종료 시간이 시작 시간과 같은 이벤트를 표시할 때 여러 곳에 흩어진 보정 코드로 임시 처리하고 있었고, 새 일정을 생성할 때 타임존이 두 번 보정되어 값이 어긋나는 문제가 있었다.
Task (과제)
- 접기 레이아웃 판정 로직을 테스트 가능한 순수 함수로 분리
- 형제 프레임을 찾는 중복 로직을 하나로 통합
- 외부 참조 컬럼 데이터의 폭 불일치를 방어하는 로직 추가
- 더보기 팝오버의 이벤트 정렬 우선순위를 명확히 정의
- 0분 이벤트 문제를 근본 원인 수준에서 해결
- 타임존 보정이 여러 곳에서 중복 적용되지 않도록 단일화
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개의 캐릭터라이제이션 테스트를 확인함. 실제 이후 리팩토링에서 얼마나 시간이 단축되는지는 다음에 유사 작업이 있을 때 비교해봐야 함
- 타임존 보정 단일화로 유사 버그 재발 가능성 감소 (추정): 보정 지점을 하나로 모으면서, 이후 새로운 화면이나 흐름이 추가되어도 중복 보정으로 인한 오차가 재발할 가능성이 줄어들 것으로 예상됨. 근거: 여러 지점에 흩어져 있던 보정 코드가 한 곳으로 정리된 것을 확인함. 실제 재발 여부는 이후 유사 기능 추가 시 확인 가능함
더 측정하면 좋은 지표
- SplitView 렌더링 로직 리팩토링 시 실제 회귀 발생 빈도: 이후 render() 관련 수정이 있을 때, 순수 함수 분리 전/후로 회귀 버그 발생률 비교
- 외부 참조 컬럼 방어 로직의 실제 적용 범위: 그리드 외에 폼, 다른 화면에서도 유사한 폭 불일치가 발생하는지 전수 점검
- 캘린더 0분 이벤트 처리 개선 전/후 코드 복잡도: 제거된 보정 코드 라인 수와 남은 로직의 복잡도(사이클로매틱 복잡도 등) 비교
- 더보기 팝오버 정렬 로직의 사용자 인지 편의성: 실제 사용자 피드백이나 사용성 테스트로 정렬 순서의 체감 효과 확인
- 두 세션 모두 남아있는 E2E 테스트 실행 결과: 실제 통과 여부와 실패 시 원인 분석
오늘 배운 것
- 데이터 배열이 헤더 정의와 항상 폭이 일치한다고 가정하면 안 된다는 것을 다시 확인함. 외부 참조 응답처럼 비표준 폭을 받을 수 있는 데이터는 인덱스 기반 접근이 안전하지 않을 수 있다는 점
- 렌더링과 상태 읽기가 섞여 있는 코드는 직접 테스트하기 어렵지만, 계산 로직만 순수 함수로 분리하면 캐릭터라이제이션 테스트를 훨씬 쉽게 작성할 수 있다는 것을 실감함. 이후 렌더링 코드를 수정할 때도 테스트만 보고 신뢰도 높게 작업할 수 있다는 것을 확인함
- 여러 조건을 동시에 봐야 하는 판정 로직은, 조건을 순서대로 나열하는 방식보다 “어떤 조건이 참이면 이것을 쓰겠다”는 의도를 먼저 함수 시그니처로 명시하고 구현하는 편이 훨씬 읽기 좋다는 것을 배움
- 공유 참조 구조를 쓰는 컴포넌트는, 한쪽(그리드)의 방어 로직 개선이 다른 쪽(폼)에도 자동으로 전파된다는 것을 확인함
- 캘린더 라이브러리가 이미 갖고 있는 개념(종료 시간이 있는 이벤트인지 여부)을 제대로 이해하고 활용하면, 여러 곳에 보정 코드를 두지 않고도 깔끔하게 처리할 수 있다는 것을 배움
- 표시용으로 임시로 만든 값이 실제 저장/조회 값에 섞여 들어가면 여러 계층에서 보정이 필요해지므로, 이런 값은 별도의 설정값으로 분리해 관리하는 것이 유지보수에 유리하다는 것을 확인함
- 값을 보정하는 지점을 하나(입력값이 처음 만들어지는 곳)로 모으는 원칙이, 하위 계층에서 중복 보정을 막는 데 효과적이라는 것을 다시 느낌
어려웠던 점 / 막힌 부분
- 접기 바(collapse bar)의 렌더링 로직에서, 화면 크기 계산 13단계와 병합 바/제목 노출 판정이 얽혀 있어 어디까지가 무조건 실행되는 부분이고 어디부터 조건부인지 헷갈렸다. 함수의 입력값과 출력값을 명확히 분리하고 나서야 한 번에 정리됨
- 형제 프레임을 찾는 로직이 세 곳에서 각각 조금씩 다른 상황(접힌 그룹 찾기, 병합 바 판정, 크기 계산)에 쓰이고 있어, 하나로 통합하면서 “형제”의 정의가 모든 곳에서 일관되게 적용되는지 검증하는 데 신경을 많이 씀
- 외부 참조 컬럼 데이터의 폭이 왜 헤더 폭과 다를 수 있는지 원인을 찾는 과정에서, 처음엔 백엔드 문제로 의심했으나 실제로는 값을 조회하는 특정 함수는 이미 결과를 정규화하는 반면, 다른 경로는 원본 데이터를 그대로 받아오기 때문이라는 것을 확인함. 근본적으로는 정규화 책임을 더 상위 계층에서 맡아야 하지만, 우선은 방어 로직으로 처리함
- 0분 이벤트 문제의 원인을 처음엔 이벤트 생성 로직의 시간 조작으로 의심했으나, 실제로는 캘린더 라이브러리 내부 구조와 공개 API의 분리 방식을 제대로 이해하지 못한 것이 원인이었음을 확인함
- 타임존 보정이 여러 지점에 흩어져 있어, 이를 모두 찾아내는 데 품이 들었음
- 시간 표시 위치(줄 안/아래)를 결정하는 조건이, 종료 시간이 없는 이벤트일 때 무조건 “아래 배치”로 가던 엣지 케이스를 뒤늦게 발견해 수정함
내일 하면 좋은 작업
- 유사한 데이터 조회 패턴을 다른 화면에서도 감사해 동일한 폭 불일치 위험이 있는지 확인
- 관련된 폼 draft 처리 커밋의 영향 범위를 외부 참조 컬럼 관점에서 재검토
- 접기 레이아웃 계산 로직의 추상화가 다른 분할 관련 컴포넌트에도 적용 가능한지 검토
- 오늘 작성한 커밋들의 로컬 테스트 확인(더보기 팝오버 정렬, 타임존 보정, 0분 이벤트 표시)
- Cypress E2E 테스트 실행 및 통과 확인
- 메인 개발 브랜치로의 병합 검토 또는 다음 캘린더 이슈 진행
한 줄 요약
오늘은 SplitView 접기 로직을 순수 함수로 정리하고 숨은 외부 참조 컬럼 버그를 방어하는 한편, 캘린더 이벤트 정렬과 타임존 이중 보정 문제를 근본 원인부터 해결한 하루였다.
댓글남기기