하던거 마무리하기!
현재 아이콘을 눌렀을 때 액션이 발생하는 아이콘 버튼 컴포넌트는 여러가지 버전이 있다.
const DailyTodo = ({ item, drag, isActive }) => {
...
const [completed, setCompleted] = useState(item.isCompleted);
const handleCheck = () => {
setCompleted(!completed);
const updatedData = {
todoId: item.id,
isCompleted: !item.isCompleted,
};
updateTodo({ accessToken: accessToken, updatedData: updatedData });
};
const checkIcon = props => {
return (
<TouchableOpacity
onPress={() => {
handleLogEvent();
handleCheck();
}}
>
<Icon
{...props}
name="checkmark-circle-2-outline"
fill={
completed ? theme['color-primary-500'] : theme['text-basic-color']
}
/>
</TouchableOpacity>
);
};
checkIcon 컴포넌트가 있고 콜백 함수로 handleCheck 함수가 있고 여기서 completed라는 상태를 바꾼다.
const [
subTodoGenerateAlertModalVisible,
setSubTodoGenerateAlertModalVisible,
] = useState(false);
const [modalVisible, setModalVisible] = useState(false);
const settingIcon = props => {
return (
<View
style={{
flexDirection: 'row',
padding: 10,
justifyContent: 'space-between',
}}
>
{!item.children.length && !generatedSubTodos.length && (
<TouchableOpacity
onPress={() => setSubTodoGenerateAlertModalVisible(true)}
>
<Icon
{...props}
name="flash-outline"
pack="eva"
fill={theme['text-basic-color']}
/>
</TouchableOpacity>
)}
<TouchableOpacity
onPress={() => {
handleLogEvent(DAILYTODO_MEATBALLMENU_CLICK_EVENT, {
time: new Date().toISOString(),
userId: userId,
todoId: item.id,
});
setModalVisible(true);
}}
>
<Icon
{...props}
name="more-horizontal-outline"
pack="eva"
fill={theme['text-basic-color']}
/>
</TouchableOpacity>
</View>
);
};
우선 보면 !item.children.length && !generatedSubTodos.length이라는 조건으로 DailyTodo 컴포넌트가 인자로 받아온 item의 children이 없다면 그리고 생성된 서브투두가 없다면 즉 현재 투두 아이템 하위에 아무것도 없다면 flash-outline 모양의 아이콘을 렌더링한다.
이걸 settingIcon 안에 넣은 이유는 ListItem 컴포넌트의 accessoryRight 인자로 넣어줘야 하기 때문.
아무튼 이렇게 아이콘 버튼 컴포넌트가 여러개 있는데 이걸 공통된 컴포넌트로 묶어야... 하나?
일단 보기 불편하니까 두 아이콘이 필요로 하는 state들을 고려해서 그냥 파일만 분리해봐야겠다.
그러면 현재 컴포넌트 폴더가 점점 더 복잡해진다. 컴포넌트 폴더 안은 딱히 구분 없이 다 우겨놓고 있기 때문!

그러고 보면 지금 들어오면 바로 보이는 메인 페이지에서 내가 컴포넌트를 잘 구분하고 있는건지 생각하게 된다.
컴포넌트를 어떻게 관리해야할까 생각도 하며 여러 글을 찾아보다가 아토믹 디자인을 활용한 디자인 시스템 도입기 이 글을 보고 이 패턴을 도입하면 좋을 것 같다고 생각이 들었다. 이유는
1. 현재 UI kitten 라이브러리를 사용하고 있어서 Atom에 해당하는 것들은 라이브러리에 의존하면 된다.
2. 한 컴포넌트가 너무 커지거나 중복된 코드가 계속 쌓이는 것을 해결할 수 있다.
정도!
그래서 이 패턴에 맞게 현재 내 코드를 봐보았다.
앱에서 투두화면을 볼 수 있는 TodayView 컴포넌트를 보면
const TodayView = () => {
const { userId } = useContext(LoginContext);
handleLogEvent(TODAYVIEW_VIEW_EVENT, {
time: new Date().toISOString(),
userId: userId,
});
return (
<CategoryProvider>
<DateProvider>
<SafeAreaView style={styles.container}>
<WeeklyCalendar />
<CategoryScroll />
<DailyTodos />
</SafeAreaView>
</DateProvider>
</CategoryProvider>
);
};
이렇게 weekly calendar를 하나의 컴포넌트로 하고 카테고리 선택하는 부분을 하나의 컴포넌트로 그리고 투두 리스트 부분을 하나로 구분했다. 이때 투두는 선택된 날짜 기준으로 필터링된다.
오케이 그러면 DailyTodos가 organisms.
//DailyTodos
...
const renderTodo = ({ item, drag, isActive }) => {
return (
<ScaleDecorator>
<DailyTodo item={item} drag={drag} isActive={isActive} />
</ScaleDecorator>
);
};
...
<GestureHandlerRootView>
<Fragment>
<KeyboardAvoidingView behavior="padding">
<DraggableFlatList
data={currentTodos}
renderItem={renderTodo}
onDragEnd={handleDragEnd}
keyExtractor={item => item.id.toString()}
/>
</KeyboardAvoidingView>
<KeyboardAccessoryView alwaysVisible androidAdjustResize>
<View>
<Input/>
</View>
</KeyboardAccessoryView>
</Fragment>
</GestureHandlerRootView>
};
그러면 DailyTodos에서 atom을 결합한 것들 중 하나의 역할만 하고 재사용성이 있을만한 molecules는 뭐가 있을까
드래그 가능한 플랫 리스트를 만들어주는 DraggableFlatList
그리고 Input박스가 있다.
그리고 DraggableFlatList에서 렌더링할 한줄 한줄에 해당하는 컴포넌트인 DailyTodo가 있다.
DailyTodo에서는 지금 하는 역할이
<>
<ListItem
title={
isEditing ? (
<Input/>
) : (
<Text>{item.content}</Text>
)
}
...
accessoryLeft={props => checkIcon(props)}
accessoryRight={props => settingIcon(props)}
onPress={...);
}}
onLongPress={drag}
isActive={isActive}
/>
<List
data={item.children}
renderItem={renderSubTodo}
contentContainerStyle={{ marginLeft: 40, paddingLeft: 40 }}
ListFooterComponent={
subTodoInputActivated ? (
<Input/>
) : null
}
/>
{generatedSubTodos.length > 0 && (
<>
<List
data={generatedSubTodos}
renderItem={renderGeneratedTodo}
contentContainerStyle={{ marginLeft: 40, paddingLeft: 40 }}
/>
<Button onPress={handleApplySelection}>반영하기</Button>
</>
)}
<TodoModal/>
<SubTodoGenerateModal/>
</>
);
};
일단 Todo를 출력하는 ListItem 부분이 있다.
그리고 SubTodo를 출력하는 List 부분이 있다.
그리고 서브투두가 생성되어 generatedSubTodos가 0 이상이면
subTodo에 해당하는 걸 출력하는 List가 있다.
그리고 Modal 두개가 있다.
중간 정리를 해보면 TodayView라는 화면을 만들기 위해서 그 중에 organism으로 DailyTodos가 들어간다. 여기서 날짜와 카테고리에 맞는 투두 데이터를 처리하고....!
정신을 차려보니 멘토링 끝나고 집에 와서 더이상 일을 못하겠다!
내일 할 것
https://fe-developers.kakaoent.com/2022/221110-ioc-pattern/
여기 참고해서 비즈니스 로직을 분리하는 것에서 적어도 props getter 패턴 적용해서 상태는 다 분리하기. 일단 PR 올리기. 그리고 마케팅!
적다보면서 생각난 점이 일을 하면서 적어도 이만큼은 해야한다 라는 기준을 전혀 생각하지 않아서 그런듯
적어도 이만큼은 해야지를 정하려면 할 일이 작게 쪼개져야 하고... 아 이럴때 누가 내 할일을 대신 쪼개주면 나는 할지 말지 판단만 하면 되고 편할 것 같은데...
이거 완전 우리 앱인 OneStep이잖아? 심리학계에서 검증된 방식으로 사람들이 쉽고 편하게 할 일을 실천할 수 있도록 LLM이 할 일을 쪼개주는 기능을 써봐야지!
그리고 오늘 팀원과 빵사오면서 하던 말이 기억에 남는다. 다리도 누울 자리를 보고 뻗는다듯이 팀원들이 다 괜찮다해줘서 시간 잡아먹고 이래도 괜찮다고 생각한듯
오늘도 반성합니다.