[TOY] 가계부 만들기 6주차 : 리팩토링 및 기능 구현 마무리
이번주 주간 목표
정리하다보니 클래스 구조부터, 디렉토리 구조, 함수구조까지 모두 엎어야겠다.
이번주는 리팩토링을 끝내고 남은 기본 기능을 구현하는데 집중해보자.
과연 이번주에는 목표한대로 진행할 수 있을까? 😂
2022.12.05 ~ 06
리팩토링
디자인 시안을 보면서 각 페이지 네이밍과 컴포넌트 구조를 돌아봤다.
동작 과정을 복기하며 그려보고,
요소의 역할을 명확히 알 수 있도록 class명을 수정하고, 계층 구조를 정리했다.
class명은 Sass의 nesting 문법 사용이 용이하도록 하되, 너무 길어지지 않도록 적당히 끊어주었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
<section class="spend">
<div class="spend-list">
<ol class="spend-list-day">
<li class="spend-list-day-item">
<div class="detail-content">
<div class="catagory">catagory</div>
<div class="title">title</div>
</div>
<span class="memo">memo</span>
</li>
</ol>
</div>
</section>
일단 위 코드같이 뎁스가 깊어지는 구조에서는 class명을 분리했는데
spend-list-day-item-detail 뭐 이렇게 명확하게 이어주는게 맞는가 고민..
그리고 semantic markup을 위한 개선도 조금 진행했다.
form, section, aside, aria-lable 등으로 일부 요소를 수정했다.
HTML <form> 잘 쓰는 법
어제도 오늘도 계속 리팩토링 중.. 내일 되어야 마무리할 수 있을듯.
아.. 고민에 고민을 거듭하느라 진도가 안나간다.
머리 싸매고 고민하는 시간이 너무 길어진다.
간단한 앱 만드는건데 이게 맞나.. 나는 바보가 아닐까.. 싶고
나름 정리를 하는 중인데도 코드가 지저분하고 길다.
당연히 지금 당장 유려한 코드를 착착 만들 수 없을 거라는걸 알지만
걱정은 된다.. 이래도되나…
일단.. 뚝심있게 꾸준히 길게보고 가보자.
2022.12.07
일단 리팩토링 끝!
css 클래스를 정리하고,
함수 동작 구조도 처음부터 한줄 한줄 훑으면서 다듬었다.
바닐라 자바스크립트로 프로젝트를 만들다보니 대부분의 모듈을
미리 만들어놓고 숨기는 방식으로 조작하다보니 이게 맞나 싶은 부분들이 많았다.
바닐라로 앱을 발전시키면서 작업해보려고 했는데,
점점 복잡한 기능을 추가하려면 상태관리가 필요하므로
리액트로 다시 만드는것이 여러모로 더 의미가 있겠다는 생각이 든다.
(바닐라로 상태관리하는 글들을 찾아보면 넘나 멋져보이고 나도 해보고싶은데
지금 나는 그럴 수 있는 단계가 아닌 것 같다.ㅎㅎㅎ)
어쨌든 낼은 남은 기능을 호로록 해치운다!
2022.12.08
소비기록 날짜 기준 내림차순 정렬 (최신순)
원래 리스트가 가진 날짜 데이터를 비교할 목적으로 dateId라는 값을 활용중이었는데,
selectedYear
-selectedMonth
-selectedDate
의 문자열 타입이었다.
정렬을 위해서 YYYYMMDD
형태의 number type으로 변환시키는 함수를 먼저 만들었다.
1
2
3
4
5
6
7
function getDateId() {
const month = selectedMonth.toString().padStart(2, "0");
const date = selectedDate.toString().padStart(2, "0");
const fullDate = selectedYear + month + date;
return parseInt(fullDate);
}
첫번째 시도
리스트를 추가하면서 만들어진 모든 ol을 함수 안에 정의하고
바로 sort 메소드를 붙이려고 했는데 에러가 났다.
querySelectorAll로 잡아온 ol들이 NodeList의 형태로 저장되었기때문에
array로 변환하는 작업이 필요했다.
(지금까진 NodeList에서도 사용 가능한 메소드만 써서 몰랐나보다.)
1
2
const element = document.querySelectorAll(".element-class");
const elementArr = Array.prototype.slice.call(element);
그런데 이렇게하면 새로 정의한 elementArr가 정렬될뿐, UI가 조작되는 것이 아니므로 실패.
두번째 시도
소비내역 저장을 누를때,
입력한 값들을 잡아 spendList 객체로 만들어서 spend라는 배열에 push하고
그 spend를 로컬에 저장하는 방식으로 작동한다.
그러니까 spend 배열 자체를 정렬해야하는 것이 아닌가 하고 아래와 같이 작성해보았다.
1
2
3
4
spends.push(spendList);
spends.sort((a, b) => b.dateId - a.dateId);
saveSpend();
generateSpendList(spendList);
spends 배열에 내용 객체를 추가하고, 정렬 한다음 로컬에 저장시켰다.
그런데 이러면 의도한 순서대로 데이터 저장은 되지만,
새로고침 해서 리스트를 아예 새로 렌더해야만 화면에 반영이 되었다.
그래서 처음 list가 생성될때 (appendChild 되는 순간)에도 dateId값을 비교해야한다.
sort 해놓은 데이터대로 렌더링되면 좋겠는데..
그렇다고 새 리스트를 등록할때마다 전체를 리렌더 할수도 없고….
이 부분에서 시간 마이 걸리는 중..
2022.12.09
와 드디어 해결했다!!
각종 경우의 수에 다 대응하는 삽질 코드를 만들고 또 만들다가
드디어 원하는 기능을 만들었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 렌더 되어있는 리스트를 잡아옴
const oldOl = document.querySelectorAll(".spend-list-day");
// 만약 렌더된게 없으면 (첫번째 리스트라면)
if (oldOl.length == 0) {
// 바로 리스트 추가
spendListDiv.appendChild(newOl);
// 그리고 등록된 내용이 없다는 문구도 가려준다.
spendEmpty.classList.add("visually-hidden");
} else {
// 렌더된 리스트가 하나라도 있으면, 그 노드의 수만큼 반복문 실행
for (let i of oldOl) {
// 새로운 리스트 id가 i 리스트 id보다 크면
if (newOl.id > i.id) {
// i 리스트 앞에 새로운 리스트를 렌더링
spendListDiv.insertBefore(newOl, i);
// 렌더링 했으니 반복문은 종료한다
return;
// 새로운 리스트 id가 i 리스트 id보다 작으면 다음 i와 반복 비교
}
}
// 새로운 리스트의 id가 가장 작으면 맨 뒤에 추가
spendListDiv.appendChild(newOl);
}
내림차순 자동 정렬 구현
항상 해결하고보면 별 것 아닌거 같은데
미로속에 있을때는 내가 할 수 있나 의심하게 된다 ㅠㅠ
2022.12.10
예산 추가 버튼 기능 구현 아니고 다시 리팩토링
예산추가 버튼을 누르면 소비내역 등록할때와 같은 모달이 뜨는 대신
input과 select 내용이 다르게 들어가도록 했고
저장하기 버튼에는 add-budget이라는 class를 추가되도록 해뒀었다.
함수를 이렇게 짜놨었다.
이제 구현해야하는 내용은
- 예산을 추가해서 등록되는 리스트는 파란색 텍스트로 보여주기
- 로컬에 저장된 예산 데이터와 추가하면서 입력한 값을 더해서 로컬 데이터 업데이트
- 예산추가 리스트 삭제 기능을 위해 리스트에 class 추가해놓기(?)
add-budget은 모달을 열때 동적으로 추가되는 class이므로 미리 잡아서 이벤트를 붙이지 않고
모달에서 저장하기 버튼을 누를때 class를 확인해서 submitAdditionalBudget
함수를 실행하도록 하려했다.
이래저래 기능이 추가되면서 기존의 함수 이름이나 구조를 수정하는 일이 많은데,
리팩토링 하면서도 그랬지만.. 고민되는 지점이 너무 많다.
비슷한 기능을 가지고 있더라도 이벤트 실행 주체가 다르다면 함수를 분리하는게 맞는지?
그럼 함수가 너무 조각조각 분리되어 있어서 더 안좋은 것 아닌가..
지금은 몇가지 메인 함수에서 조건값에 따라 다양한 기능을 실행할 수 있도록 했는데,
너무 포괄적인 기능을 수행하는건가?
어떤쪽이 코드의 가독성을 더 떨어뜨리는건지 판단이 잘 안된다.
바보같은 고민을 한 것 같다.
하나의 함수는 하나의 목적에 맞는 코드만을 포함하고, 세분화 시킨다.
그렇게 모듈화를 시켜서 재사용성을 높이는게 맞겠다.
이것도 할 수 있고, 저것도 할 수 있는 코드는 안좋은 코드가 맞다.
class naming convention에 대한 글을 읽다가,
함수명 작성에 대한 내용이 있었는데 그때 그런 내용이 있었다.
함수명은 그 함수가 어떤 기능을 실행하는지 명확하게 알 수 있어야 한다.
이럴수도 있고 저럴수도 있는 중의적 표현은 좋지 못하다.
그럼 이제 함수를 분리해보자.
예상치 못하게 다시 리팩토링 시작 😂
TMI👀
요즘 내가 너무 바보같아서 자괴감에 빠져있는데
이 영상 보고 그러지 말아야겠다고 생각했다.
하다보면 분명 답을 찾게되고 익숙해지면 실력은 자연스럽게 생긴다. 길게 보고 가자.
TMI👀
money manager 보다는 expense tracker 라는 표현이 앱의 목적에 더 맞는것 같아서 수정했다.
TMI👀
고민하고 실행하고 해결하는 매일 매일. 조금만 더 자신감 갖고 행복하게 하면 좋겠다.
그리고 자연스럽게 영어 속에 빠지게 되는 것도 좋다. 딱 내가 원하던거! 나 왜 진작 개발자 안했지??
Leave a comment