
안녕하세요! 방구석에서 코딩으로 자본주의 생존 도구를 뚝딱뚝딱 만들어가고 있는 1인 개발자입니다.
지난 2편에서는 엑셀의 답답함을 벗어던지기 위해 슬라이더 UI를 도입하고, 파란색과 초록색 컬러 심리학을 활용해 디자인 뼈대를 세운 이야기를 들려드렸죠. 자, 겉모습을 예쁘게 스케치했으니 이제 진짜 생명력을 불어넣을 차례입니다. 오늘 3편에서는 이 프로젝트의 엔진 역할을 하는 프론트엔드 프레임워크 초기 세팅과, 머리를 쥐어뜯게 만들었던 복잡한 '상태(State) 관리' 전략에 대해 이야기해 볼까 합니다.
빠르고 가볍게 시작하자! 시대의 대세 Vite
과거에는 리액트(React) 프로젝트를 시작할 때 무조건 'Create React App(CRA)'이라는 명령어를 국룰처럼 썼습니다. 하지만 저는 이번 프로젝트에서 과감하게 CRA를 버리고 Vite를 선택했습니다.
Vite를 선택한 이유는 아주 단순하고 명확합니다. "압도적으로 빠르기" 때문입니다. CRA는 코드를 수정하고 저장할 때마다 화면에 반영되기까지 은근히 무거운 로딩 시간이 걸리곤 했어요. 하지만 Vite는 프랑스어로 '빠르다'는 뜻을 가진 이름답게, 저장을 누르는 즉시 번개처럼 브라우저 화면이 새로고침 됩니다. 1인 개발자에게 시간과 쾌적한 개발 환경은 생명이잖아요? 터미널에 간단한 명령어 한 줄을 치는 것만으로 눈 깜짝할 사이에 빠르고 가벼운 리액트 프로젝트 초기 세팅이 끝났습니다.
위기 발생: 변수가 도대체 몇 개야?
프로젝트 세팅을 마치고 본격적으로 코드를 짜려는데, 곧바로 거대한 벽에 부딪혔습니다. 바로 이 계산기가 품고 있는 어마어마한 양의 '입력 변수'들 때문이었죠.
한번 생각해 볼까요? 사용자가 이 시뮬레이터에서 조작해야 하는 값들만 대충 세어봐도 꽤 많습니다. 현재 가진 시드머니, 매월 추가로 붓는 투자금, 내가 최종적으로 받고 싶은 목표 월 배당금, 예상하는 연 배당수익률, 배당성장률, 게다가 물가상승률 반영 여부를 묻는 스위치와 절세계좌(ISA) 활용 여부를 묻는 스위치까지... 이 모든 것들이 화면 안에서 실시간으로 변하고 서로 영향을 주고받아야 합니다.
리액트에서는 화면에 변하는 값을 보여주기 위해 useState라는 기능을 사용합니다. 만약 아무 생각 없이 이 변수들을 하나하나 따로 관리하려고 했다면 제 코드는 아마 이렇게 끔찍한 모습이 되었을 겁니다.
"시드머니 상태 만들고~ 추가 투자금 상태 만들고~ 목표액 상태 만들고..."
코드 상단에 useState만 10줄 가까이 빽빽하게 늘어선 모습을 상상해 보세요. 코드가 길어지는 것도 문제지만, 나중에 값을 하나 수정할 때마다 어떤 상태 업데이트 함수를 불러와야 하는지 헷갈려서 버그가 터지기 딱 좋은 소위 '스파게티 코드'가 될 게 뻔했습니다.

해결책 1: 컴포넌트를 깔끔하게 쪼개기
이 혼돈을 잠재우기 위해 제가 가장 먼저 한 일은 '컴포넌트(Component)의 명확한 분리'였습니다. 하나의 도화지(App.jsx)에 모든 걸 다 그려 넣지 않고 구역을 나누는 거죠.
크게 화면을 반으로 쪼갰습니다. 왼쪽은 사용자가 값을 조작하는 [입력 패널 컴포넌트], 오른쪽은 그 값을 바탕으로 결과를 보여주는 [결과 패널 및 차트 컴포넌트]로 나누었습니다. 이렇게 역할을 분리해 두면 코드를 읽기가 훨씬 편해집니다. 왼쪽 컴포넌트는 오직 '값을 입력받는 일'에만 집중하고, 오른쪽 컴포넌트는 '값을 예쁘게 보여주는 일'에만 집중하게 되니까요.
그럼 여기서 질문 하나! 왼쪽 컴포넌트에서 사용자가 슬라이더를 쓱 밀어서 조작한 값을, 오른쪽 컴포넌트가 어떻게 알고 화면을 바꿀까요? 이게 바로 리액트의 핵심입니다. 두 컴포넌트의 공통 부모인 최상단 컴포넌트(App)에 모든 데이터의 본부를 차려두고, 자식들에게 필요한 데이터만 쏙쏙 내려보내 주는(Props) 방식으로 데이터의 흐름을 위에서 아래로 깔끔하게 정리했습니다.
해결책 2: 상태(State)를 하나의 '객체'로 묶어버리기
컴포넌트를 나눴어도 여전히 수많은 변수들을 관리해야 하는 문제는 남아있었죠. 저는 useState를 10번 넘게 쓰는 대신, 이 모든 입력값들을 하나의 '객체(Object)'로 예쁘게 포장해서 관리하는 전략을 택했습니다.
마치 여행 갈 때 양말, 칫솔, 수건을 각각 따로 들고 가는 게 아니라 '여행용 캐리어' 하나에 차곡차곡 담아서 끌고 가는 것과 같은 원리입니다. '사용자 입력값'이라는 커다란 캐리어를 하나 만들고, 그 안에 시드머니, 투자금, 수익률 등의 데이터를 칸막이 쳐서 담아두는 거죠.
이렇게 객체로 묶어버리면 놀라운 마법이 일어납니다. 슬라이더를 움직일 때마다 각각 다른 함수를 부를 필요 없이, 단 하나의 '업데이트 함수'만 만들어두면 됩니다. "어? 사용자가 시드머니 슬라이더를 움직였네? 그럼 다른 짐들은 그대로 두고, 캐리어 안에서 시드머니 칸막이 내용물만 쏙 바꿔치기해야겠다!" 이런 식으로 로직이 돌아가게 짰습니다. 덕분에 코드는 믿을 수 없을 만큼 짧아졌고, 나중에 새로운 기능(예를 들어 연금저축 기능 추가)을 넣고 싶을 때도 캐리어에 칸막이 하나만 쓱 추가하면 되니 유지보수도 엄청나게 편해졌습니다.

튼튼한 뼈대 위에 살을 붙일 준비 완료!
Vite로 빠릿빠릿한 개발 환경을 구축하고, 얽히고설킨 수많은 입력 변수들을 객체로 묶어 통제권을 쥐고 나니 마음이 아주 편안해졌습니다. 컴포넌트 구조도 좌우로 예쁘게 나눠놔서 데이터가 물 흐르듯 위에서 아래로 흐르는 튼튼한 뼈대가 완성되었죠.
프론트엔드 개발에서 상태 관리가 엉키면 나중에 차트를 그리거나 계산을 할 때 원인 모를 늪에 빠지기 십상입니다. 하지만 이렇게 초반에 구조를 탄탄하게 잡아둔 덕분에 다음 단계로 아주 매끄럽게 넘어갈 수 있었습니다.
자, 이제 남은 건 이 깔끔하게 정리된 데이터들을 재료로 삼아, 사용자가 원하는 '은퇴 날짜'를 요리해 내는 일입니다! 다음 4편에서는 수학 공식 하나 쓰지 않고 오직 자바스크립트(JavaScript) 프로그래밍의 논리만으로 [올인원 배당 파이어족 은퇴 시뮬레이터 메이킹 로그 #04] 배당 재투자 복리의 마법, JavaScript 로직으로 완벽 구현하기 이야기를 들려드릴게요. 기대하셔도 좋습니다. 다음 편에서 만나요!
[올인원 배당 파이어족 은퇴 시뮬레이터 메이킹 로그 #04] 배당 재투자 복리의 마법, JavaScript 로직
안녕하세요! 방구석에서 코딩으로 저만의 자본주의 생존 무기를 벼려내고 있는 1인 개발자입니다.지난 3편에서는 리액트(React)를 켜고 수많은 입력값들을 하나의 캐리어(객체)에 깔끔하게 담아
code-bricks.tistory.com