[개발 회고] 접기 상태에 ‘디자인 기본값’과 ‘내 설정’을 동시에 두는 법
접기 상태에 ‘디자인 기본값’과 ‘내 설정’을 동시에 두는 법
구현 계획 — 프레임 접기(content collapsed) 개인화
배경
프레임을 접었다 폈다 하는 상태를, 이미 같은 방식으로 다루고 있던 “분할 비율(화면을 나누는 비율)” 설정과 동일한 패턴으로 개인화하기로 했다. 여기서 “개인화”란 다음 세 층위를 구분해서 관리하는 것을 뜻한다.
- 디자인 기본값 — 화면을 설계하는 사람이 정해둔 기본 접힘 상태
- 내 설정(개인화) — 실제 사용자가 화면을 보다가 임의로 접거나 편 상태. 새로고침해도 유지된다
- 초기화 — 사용자가 “설정 초기화”를 누르면, 개인화 값은 사라지고 다시 디자인 기본값으로 돌아간다
핵심은 이 세 층위가 서로 충돌하지 않고 정확한 순서로 적용되어야 한다는 점이다. 편집 화면에 들어갈 때는 항상 디자인 기본값이 보여야 하고, 실제 사용 화면에서는 각자 개인화한 값이 유지되어야 한다.
전체 구조를 비유로 설명하면
이 기능을 “메모지와 도장” 비유로 생각하면 이해하기 쉽다.
- 디자인 기본값은 서버에 찍혀 있는 “원본 도장”이다. 화면을 처음 열 때마다 이 도장 값을 프레임 옆에 살짝 옮겨 적어둔다(원본은 그대로 두고, 참고용 사본만 만드는 셈).
- 실제로 화면에 보이는 상태는 두 가지 형태로 동시에 표현한다. 하나는 “접힌 프레임들의 명단”(목록), 다른 하나는 각 프레임에 붙은 “접힘 여부 스티커”(값 하나). 이 둘은 항상 같은 상태를 가리키도록 짝을 맞춰 관리한다 — 명단에 이름이 있으면 스티커도 반드시 “접힘”이어야 한다.
- 개인화 값은 사용자별로 보관하는 “내 메모장”에 따로 적어둔다. 이 메모장은 기존에 분할 비율을 저장하던 곳과 같은 서랍을 쓴다.
이렇게 나누면, “화면을 처음 열 때 어떤 상태로 보여줄지”, “사용자가 직접 바꾼 값을 어떻게 저장할지”, “초기화할 때 무엇을 지우고 무엇을 남길지”를 각각 독립적으로 다룰 수 있다.
지켜야 할 제약
- 이 작업은 프론트엔드 범위에서만 진행하고, 서버 쪽 로직은 건드리지 않는다. 서버가 내려주는 값의 이름과 프론트가 쓰는 이름을 통일해서, 값을 주고받을 때 별도로 이름을 바꿔주는 변환 과정을 두지 않는다.
- 이번 범위는 “접기/펴기”만 다루고, “화면 전체로 확대”하는 기능은 건드리지 않는다.
- 프레임을 다른 위치로 옮기는 로직에는 접힘 상태 관련 코드를 추가하지 않기로, 설계 단계에서 이미 검토를 마치고 제외를 확정했다.
작업 순서 (테스트 먼저, 구현은 그다음)
전체 작업은 “이미 검증된 패턴(분할 비율)을 그대로 복제한다”는 원칙 아래, 각 단계마다 먼저 실패하는 검증을 만들고 나서 최소한의 구현으로 통과시키는 순서로 진행하도록 계획했다. 단계는 대략 다음과 같은 흐름이다.
- 저장할 때 오가는 값의 모양 정의 — 프레임 정보를 서버로 보낼 때와 화면 구성 정보를 만들 때, “접힘 여부”라는 값이 자연스럽게 함께 실려가도록 관련 타입들에 필드를 추가한다.
- 화면에서 쓰는 프레임 정보에 필드 추가 — “지금 실제로 접혀 있는지”와 “디자인이 정한 기본값은 무엇인지”를 각각 따로 들고 있을 자리를 만든다.
- 접힘 상태를 바꾸는 함수가 항상 짝을 맞추도록 보장 — “접힌 프레임 명단”과 “프레임에 붙은 접힘 스티커”가 어떤 경우에도 서로 어긋나지 않도록, 상태를 바꾸는 함수 하나에서 둘을 항상 함께 갱신하게 만든다.
- 화면을 처음 열 때 기본값과 개인화 값을 순서대로 반영 — 개인화된 값이 있으면 그것을, 없으면 디자인 기본값을 적용한다.
- 비로그인 공개 화면에서는 개인화 없이 서버 값을 그대로 반영 — 이 경로는 사용자 구분이 없는 뷰이므로 더 단순하게, 서버가 준 값을 그대로 쓴다.
- 사용자가 직접 접었다 펼 때는 지금 보고 있는 화면이 편집 화면인지 사용 화면인지에 따라 갈래를 나눈다 — 편집 화면에서 바꾸면 그 프레임 자체의 “수정됨” 표시가 붙고(디자인을 바꾸는 셈), 사용 화면에서 바꾸면 개인 설정 서랍에 저장된다(내 화면만 바뀌는 셈).
- 편집 화면에 들어갈 때는 개인화 값과 무관하게 디자인 기본값으로 강제로 맞춘다 — 디자인을 수정하는 사람은 항상 원본 상태를 봐야 하기 때문이다.
- 편집을 취소할 때는 원래 데이터로 되돌리면서, 개인화 값도 다시 입혀준다 — 되돌리기 로직이 개인화까지 함께 복원하지 않으면, 취소했는데도 디자인 기본값이 그대로 남는 어색한 상태가 생기기 때문이다.
- “설정 초기화” 버튼을 누르면, 개인화로 디자인 기본값과 달라져 있던 프레임들만 골라 다시 기본값으로 되돌린다.
- 전체 테스트와 빌드를 돌리고, 실제 화면에서 다섯 가지 시나리오(접고 저장 → 새로고침 유지 확인 → 펴고 새로고침 유지 확인 → 초기화 → 편집 화면 재진입)를 수동으로 확인한다.
각 단계는 “이미 통과하는 것처럼 보이는 검증이라도, 실제 로직이 그 자리에 심어져 있는지”를 별도로 확인하도록 설계했다. 인라인으로 미리 재현해본 로직과, 실제 프로덕션 코드 안에 심어진 로직이 다를 수 있기 때문이다.
영향 범위
프론트엔드의 상태 저장소(스토어) 계층과 관련 타입 정의, 그리고 저장 시 서버로 보내는 데이터 구성 로직이 주요 영향 범위다. 서버 코드는 이번 계획에서 직접 수정하지 않으며, 일부 백엔드 파일은 “이런 예외 처리가 필요할 수 있다”는 제안만 남기고 실제 변경은 하지 않는다.
왜 이런 순서로 설계했는가
가장 중요한 원칙은 “이미 검증된 패턴을 그대로 복제한다”는 것이었다. 분할 비율 기능이 이미 디자인 기본값·개인화·초기화 세 층위를 다루는 구조를 갖고 있었기 때문에, 새로운 기능(접기 상태)을 처음부터 새로 설계하기보다 기존 구조의 옆자리에 나란히 심는 방식을 택했다. 이렇게 하면 기존 기능이 이미 겪었던 엣지 케이스(동시 수정, 취소 시 복원, 초기화 시 선택적 복원 등)를 다시 발견할 필요 없이, 같은 해결책을 그대로 재사용할 수 있다.
또한 각 단계마다 “실패하는 검증을 먼저 만든다”는 순서를 지킨 이유는, 단계가 많고 서로 의존 관계가 있는 작업일수록 “구현은 됐는데 실제로는 연결이 안 되어 있는” 상태를 조기에 잡아내기 위해서다. 특히 화면을 처음 열 때 상태를 반영하는 로직처럼, 실제 서버 통신 콜백 안에 있어 통째로 재현하기 어려운 부분은 “그 콜백이 도달하는 최종 상태”만 검증하는 방식을 택해, 테스트의 실용성과 신뢰도 사이의 균형을 맞췄다.
검증 계획
전체 자동 테스트와 빌드를 돌려 회귀가 없는지 확인한 뒤, 실제 개발 서버에서 다음 시나리오를 사람이 직접 확인한다.
- 여러 프레임이 있는 화면을 편집 모드로 열고, 프레임 하나를 접은 뒤 저장한다.
- 사용 화면으로 돌아와 새로고침해도 접힌 상태가 유지되는지 확인한다(디자인 기본값 반영).
- 사용 화면에서 그 프레임을 펴본다. 새로고침해도 편 상태가 유지되는지 확인한다(개인화 저장).
- 설정 초기화를 실행해, 다시 접힌 상태(디자인 기본값)로 돌아오는지 확인한다.
- 편집 모드로 다시 들어가서, 개인화(펴짐) 여부와 무관하게 디자인 기본값(접힘)이 보이는지 확인한다.
댓글남기기