리액트 프로젝트를 시작할 때 CRA
를 많이 사용할 것이다. 나도 웹팩 설정을 통해 하고 싶지만 수련이 부족해서 CRA를 사용하고 있다.
하지만 가장 고민은 앞으로 컴포넌트들을 만들어 나가면서 어떻게 파일들을 적절한 위치에 넣을지 항상 고민을 했다.
내 생각은 그렇다.
내가 만들려고 하는 컴포넌트에 필요한 것들이 전부 분리가 된다면 읽어 내려갈 때 훨씬 편할 것이다. ui와 로직을 분리해서 세부 구현 상황을 몰라도 아,, 이게 이런 컴포넌트구나! 하는 코드가 좋은 코드이지 않을까 하는 생각을 했다.
그래서 나는 react의 타입, styled-components로 제작된 스타일들을 다른 파일로 분리해서 import 시켜 컴포넌트를 구성했다.
나는 너무 만족했다. 엘리스 부트캠프에서 3번의 프로젝트를 하면서 2차와 3차 프로젝트에서 이런 폴더 구조를 잡아서 만족스러운 규칙이었다고 생각했다.
스타일 타입이 전부 분리가 되어 한 파일에서 관리가 가능하니 수정할 때 이 파일 저 파일 옮길 필요가 없어 좋았다고 생각했다.
하지만 그건 나만
좋은 방법이었다. feconf를 보면서, 유명 문서를 보면서 내가 만들었던 폴더가 미래에 프로젝트에 참여하지 않은 사람이 접하기에는 좋지 않은 구조일 수 있겠다는 생각을 하게 됐다.
모든 것이 분리되어 있다 보니, 해당하는 곳을 찾기 위해 여러 파일을 돌아봐야 하는 문제가 있음을 깨닫게 되었다.
이상한 관심사의 분리를 적용한 나의 패착
..!
폴더 구조에 정답은 없지만 많은 글들을 통해 co-location
이 지금 나에게 적합하다고 생각했다.
이는 세 가지 기준을 통해 내린 결론이다.
첫 번째, Maintainability
두 번째, Applicability
세 번째, Ease of use
남이 봤을 때 정말 보기 좋은 코드일까 원래 내가 짰던 코드를 여기서 말하는 데로 바꿔보겠다.
const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const validation = authValidation({ email, password });
const handleOnChangeEmail = (e: React.ChangeEvent<HTMLInputElement>) => {
setEmail(e.target.value);
};
const handleOnChangePassword = (e: React.ChangeEvent<HTMLInputElement>) => {
setPassword(e.target.value);
};
const handleOnSubmit = async (e: React.ChangeEvent<HTMLFormElement>) => {
e.preventDefault();
const authInfo = { email, password };
try {
const { message, token } = await logIn(authInfo);
localStorage.setItem(token, "userToken");
} catch (erroe) {
alert("로그인 실패..! 다시 시도해주세요.");
}
};
return (
<Container>
<LoginForm onSubmit={handleOnSubmit}>
<Input
required
onChange={handleOnChangeEmail}
type="text"
types="auth"
/>
<Input
required
onChange={handleOnChangePassword}
type="password"
types="auth"
/>
<SubmitBtn type="submit" disabled={!validation} />
</LoginForm>
</Container>
);
};
export default Login;
일단 바꿔야 할 부분은 style component를 같은 폴더에 따로 파일을 만들어 분리했는데 이를 같은 파일에 위치시켜 수정에 편리함을 줘야겠다. 만약에 스타일이 너무 길어졌다면 따로 분리해도 좋겠지만 스타일이 너무 길다고 느껴진다면..? 파일을 따로 만들겠지만 그럴 일이 많이 있을 것 같지 않다.
그리고 onSubmit 로직과 onChange 로직이 굳이 해당 컴포넌트에서 세부적으로 보일 필요는 없어 보이니 hook으로 분리해서 관심사 분리까지 적용해보자.
Props가 있었다면 해당 타입도 이 컴포넌트에서 정의했을 것이다.
// interface ??
const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const handleChangeEmail = useInput({ setValue: setEmail });
const handleChangePassword = useInput({ setValue: setPassword });
const validation = authValidation({ email, password });
const handleOnSubmit = useAuthSubmit({
email,
password,
api: logIn,
locationTo: "/",
});
return (
<Container>
<LoginForm onSubmit={handleOnSubmit}>
<Input
type="text"
types="auth"
onChange={handleChangeEmail}
required={true}
/>
<Input
type="password"
types="auth"
onChange={handleChangePassword}
required={true}
/>
<SubmitBtn type="submit" disabled={!validation}>
로그인
</SubmitBtn>
</LoginForm>
</Container>
);
};
const Container = styled.section``;
const LoginForm = styled.form``;
const SubmitBtn = styled.button``;
export default Login;
view와 로직을 분리시키고 컴포넌트의 what에 해당 하는 부분들을 같은 파일로 묶으니 수정에 있어 편리함이 증가한 기분이 든다. 하지만 이 컴포넌트에서 많은 수정이 일어날 것 같지 않아 그 힘을 아직 느끼지 못했다.
앞으로 프리온보딩 과제를 진행하면서 정말 많은 문서들을 보면서 내가 그동안 짠 코드들이 뭐가 문제였는지 더 생각해 볼 것이다. 이미 벌써 너무 많이 잘못을 저질러 반성이 많이 되고 있다.
잘못을 저질렀지만 그 코드를 짤 때 나는 최선을 다했고, 이 글을 쓰기까지 저 코드를 바꾸는데 최선을 다 했다.
그런데 더 실력이 쌓여지고 이 코드를 보면 또 다른 문제점들이 보이면서 그 땐 왜 그랬지 하겠지...?
그래서 코딩이 재밌는 것 같다. 하나씩 알아가면서 나에 대해 지속적으로 리마인드를 할 수 있어서 너무 재밌는 것 같다.
그러니까 이렇게 좋은 정보들을 알려면 영어공부 잘하자^^ 물 흐르듯 영어를 읽었다면 개발짱이 됐을지도..?(ㅈㅅ)