안녕하세요 :)
이 주간 정신없이 데모를 위한 웹어플을 만들고 나니 벌써 5월이 되었네요 ㅎㅎ
오늘은 너저분하게 흐트러져 있는 코드를 리펙토링 하는 시간을 가져보았습니다.
사실 사수로부터 체계적으로 배운 코딩이 아니라 리펙토링이 다소 엉성할 수 있습니다.
그냥 이렇게 하는 사람도 있구나하는 가벼운 느낌으로 참고해 주시면 감사하겠습니다.
리펙토링 코드:
import styled from "styled-components";
import Button from "ui/button/Button";
import { RepeatClockIcon } from '@chakra-ui/icons';
import { useAppDispatch, useAppSelector } from "store/hooks";
import { setIsOpen } from "store/history/historySlice";
import { getLambdaData } from "api/lambda";
import { setData, setIsLoading, resetData } from "store/data/dataSlice";
import { generateKey } from "../../../util/util";
const Container = styled.div`
padding: 16px 24px;
border-bottom: 1px solid #ececf1;
height: 65px;
display: flex;
align-items: center;
flex: 0 0 auto;
justify-content: space-between;
`
const Wrapper = styled.div`
display: flex;
gap: 5px;
`
const Title = styled.div`
font-weight: 500;
font-size: 18px;
`
const Subheader = () => {
const dispatch = useAppDispatch();
// const openHistory = () => dispatch(setIsOpen());
const filters = useAppSelector((state) => state.filter.filters);
const submit = async () => {
dispatch(resetData());
dispatch(setIsLoading(true));
const res = await getLambdaData(filters);
if (res) dispatch(setData(res))
else dispatch(setData([]));
}
return (
<>
<Container>
<Title>Playground</Title>
<Wrapper>
<Button
type="primary"
onClick={submit}
>
Submit
</Button>
{/* <Button
type="white"
onClick={openHistory}
>
<RepeatClockIcon />
</Button> */}
</Wrapper>
</Container>
</>
)
}
export default Subheader;
코드의 복잡도는 정말 주관적인 개념인 것 같습니다.
큰 규모의 회사에서 일하는 개발자분들의 경우 코드를 깔끔하고 경결하게 유지하는 게 무엇보다 중요하다고 강조하는 반면,
리덕스 라이브러리를 만든 개발자의 블로그에서는 리펙토링에 목멜 필요없이 그 필요성이 저절로 느껴질 때 자연스럽게 하면 된다고 하니까요.
여하튼 위의 코드를 보면 크게 불편한 부분이 하나 보입니다.
스타일과 렌더링 코드가 한 군데 섞여 있죠.
우선 이 부분을 떼어내도록 하겠습니다.
1. 스타일과 렌더링코드 구분
//SubheaderStyles.tx
import styled from "styled-components";
export const Container = styled.div`
padding: 16px 24px;
border-bottom: 1px solid #ececf1;
height: 65px;
display: flex;
align-items: center;
flex: 0 0 auto;
justify-content: space-between;
`
export const Wrapper = styled.div`
display: flex;
gap: 5px;
`
export const Title = styled.div`
font-weight: 500;
font-size: 18px;
`
//Subheader.tsx
import Button from "ui/button/Button";
import { RepeatClockIcon } from '@chakra-ui/icons';
import { useAppDispatch, useAppSelector } from "store/hooks";
import { setIsOpen } from "store/history/historySlice";
import { getLambdaData } from "api/lambda";
import { setData, setIsLoading, resetData } from "store/data/dataSlice";
import { generateKey } from "../../../util/util";
import {
Container,
Wrapper,
Title,
} from './SubheaderStyles'
const Subheader = () => {
const dispatch = useAppDispatch();
// const openHistory = () => dispatch(setIsOpen());
const filters = useAppSelector((state) => state.filter.filters);
const submit = async () => {
dispatch(resetData());
dispatch(setIsLoading(true));
const res = await getLambdaData(filters);
if (res) dispatch(setData(res))
else dispatch(setData([]));
}
return (
<>
<Container>
<Title>Playground</Title>
<Wrapper>
<Button
type="primary"
onClick={submit}
>
Submit
</Button>
{/* <Button
type="white"
onClick={openHistory}
>
<RepeatClockIcon />
</Button> */}
</Wrapper>
</Container>
</>
)
}
export default Subheader;
스타일과 관련된 코드를 SubheaderStyles.ts로 떼어내니 Subheader.tsx는 렌더링과 부수적인 비즈니스로직 코드만이 남게 되었습니다.
2. 사용하지 않는 코드 제거
그리고 테스트 과정에서 붙여놓았던 사용하지 않는 코드나 console.log와 같은 코드를 삭제해 줍니다.
위 코드의 경우 import { generateKey } from "../../../util/util";를 사용하지 않으니 삭제토록 하겠습니다.
import Button from "ui/button/Button";
import { RepeatClockIcon } from '@chakra-ui/icons';
import { useAppDispatch, useAppSelector } from "store/hooks";
import { setIsOpen } from "store/history/historySlice";
import { getLambdaData } from "api/lambda";
import { setData, setIsLoading, resetData } from "store/data/dataSlice";
import {
Container,
Wrapper,
Title,
} from './SubheaderStyles'
const Subheader = () => {
const dispatch = useAppDispatch();
// const openHistory = () => dispatch(setIsOpen());
const filters = useAppSelector((state) => state.filter.filters);
const submit = async () => {
dispatch(resetData());
dispatch(setIsLoading(true));
const res = await getLambdaData(filters);
if (res) dispatch(setData(res))
else dispatch(setData([]));
}
return (
<>
<Container>
<Title>Playground</Title>
<Wrapper>
<Button type="primary" onClick={submit}>Submit</Button>
{/* <Button type="white" onClick={openHistory}><RepeatClockIcon /></Button> */}
</Wrapper>
</Container>
</>
)
}
export default Subheader;
3. 렌더링과 비즈니스 코드 구분
사실 코드의 양이 그렇게 많지 않아서 이 정도의 리펙토링만으로도 큰 문제는 없어 보입니다. 하지만 저는 비즈니스코드와 렌더링에 관여하는 코드를 구별하는 편을 선호합니다. SOLID 법칙에 따르면 하나의 모듈은 하나의 역할에만 충실해야 합니다. 하지만 컴포넌트 안에 렌더링과 관련된 코드와 비즈니스 코드가 섞여있으면 하나의 역할에만 충실하기 어렵기 때문입니다.
커스텀 훅을 이용해 코드를 나누어 보겠습니다.
//hooks.useSubmit.ts
import { useAppDispatch, useAppSelector } from "store/hooks";
import { setData, setIsLoading, resetData } from "store/data/dataSlice";
import { getLambdaData } from "api/lambda";
const useSubmit = () => {
const dispatch = useAppDispatch();
const filters = useAppSelector((state) => state.filter.filters);
const submit = async() => {
dispatch(resetData());
dispatch(setIsLoading(true));
const res = await getLambdaData(filters);
if (res) dispatch(setData(res))
else dispatch(setData([]));
}
return [submit]
}
export default useSubmit;
import Button from "ui/button/Button";
import { RepeatClockIcon } from '@chakra-ui/icons';
import {
Container,
Wrapper,
Title,
} from './SubheaderStyles'
import useSubmit from "./hooks/useSubmit";
const Subheader = () => {
// const openHistory = () => dispatch(setIsOpen());
const [submit] = useSubmit()
return (
<>
<Container>
<Title>Playground</Title>
<Wrapper>
<Button type="primary" onClick={submit}>Submit</Button>
{/* <Button type="white" onClick={openHistory}><RepeatClockIcon /></Button> */}
</Wrapper>
</Container>
</>
)
}
export default Subheader;
위처럼 커스텀 훔에 submit과 관련된 코드를 넣으니
Subheader에는 렌더링과 관련된 코드만 깔끔하게 정리되었습니다.
'Front-End > React' 카테고리의 다른 글
[React] lambda-client request 취소하기 (0) | 2023.05.15 |
---|---|
[React] Auth0로 authentication처리 (0) | 2023.05.15 |
[React] 플랫폼 메인구조(헤더, 사이드바, 푸터) 특정 페이지에만 적용하기 (0) | 2023.03.02 |
[React] React를 왜 만들었을까? (0) | 2023.02.17 |
[React] 모바일 청첩장에 벚꽃 배경 만들기 (0) | 2023.01.10 |