더 나은 추상화 만들기 - 메뉴아이템
[번역] DRY - 잘못된 추상화의 일반적인 원인을 읽고 작성한 코드를 분석해본 글입니다.
위 포스트을 읽으며 DRY가 잘못되는 과정에 작성된 코드가 내가 작성한 코드와 비슷해서 생각해보게 되었습니다.
코드를 읽을 때 가장 좋은 코드는 아래의 그림 왼쪽처럼 위에서 아래로 쭉 읽어나가기만 하면 되는 코드입니다.
하지만 내 코드는 오른쪽 그림만큼은 아니지만, 내가 작성한 메뉴 아이템을 확인하려면 위로 올라가서 읽어야합니다.
코드를 줄이기 위해 객체를 사용하여, 반복할 내용을 묶고 반복문을 사용해서 코드의 중복을 줄이는 방법을 사용하였기 때문입니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
const adminNav: IAdminNavItem[] = [
{
path: "/admin/users",
name: "사용자 관리",
icon: <UserIcon />
},
{
path: "/admin/report-user",
name: "신고된 사용자 관리",
icon: <ReportIcon />
},
{
path: "/admin/unverified-reviews",
name: "미승인 후기 관리",
icon: <DashboardUnapprovedReviewIcon />,
$iconSize: 16
}
];
function AdminSidebar() {
const { pathname } = useLocation();
return (
<Container>
<Logo>
<NaedonnaesanTextLogo />
</Logo>
<LinkToService>
<AdminNavItem
path="/"
icon={<DashboardLinkIcon />}
name="사이트 바로가기"
/>
</LinkToService>
<div>
<NavSectionTitle>사이트관리</NavSectionTitle>
<nav>
{adminNav.map((nav) => (
<AdminNavItem
isActive={pathname === nav.path}
{...nav}
key={nav.name}
/>
))}
</nav>
</div>
</Container>
);
}
그래서 포스트를 참고하여 작성해두었던 컴포넌트에 직접 인자를 전달하는 방법으로 변경해보았습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
function AdminSidebar() {
return (
<Container>
<Logo>
<NaedonnaesanTextLogo />
</Logo>
<LinkToService>
<AdminNavItem
path="/"
icon={<DashboardLinkIcon />}
name="사이트 바로가기"
/>
</LinkToService>
<div>
<NavSectionTitle>사이트관리</NavSectionTitle>
<nav>
<AdminNavItem
path="/admin/users"
name="사용자 관리"
icon={<UserIcon />}
/>
<AdminNavItem
path="/admin/report-user"
name="신고된 사용자 관리"
icon={<ReportIcon />}
/>
<AdminNavItem
path="/admin/unverified-reviews"
name="미승인 후기 관리"
icon={<DashboardUnapprovedReviewIcon />}
$iconSize={16}
/>
</nav>
</div>
</Container>
);
}
isActive 인자를 매번 전달하는 건 옳지 않다는 생각이 들어, AdminNavItem
에서 주소를 비교하여 active 클래스를 추가하고 제거하도록 설정했습니다.
1
2
3
4
5
6
7
8
9
function AdminNavItem({ icon, name, path, $iconSize }: IAdminNavItem) {
const { pathname } = useLocation();
return (
<NavItem to={path} className={pathname === path ? "active" : ""}>
<Icon fill="#fff" icon={icon} width={20} $iconSize={$iconSize} />
<Title>{name}</Title>
</NavItem>
);
}
변경하니 메뉴아이템의 정보를 확인하기 위해 코드를 다시 올려서 확인할 필요가 없어졌습니다.
비교
통합된 접근 방식
장점:
- 코드의 중복을 줄여 유지보수가 용이
- 메뉴 아이템이 많을 때 코드의 길이를 줄일 수 있음
단점:
- 특정 메뉴 아이템을 수정하거나 내용을 확인할 때 스크롤해야 하기 때문에 불편할 수 있음
- 구조가 복잡해져 가독성이 떨어짐
분리된 접근 방식
장점:
- 각 메뉴의 아이템 정보를 한 눈에 확인할 수 있어 수정에 용이
- 각 아이템 속성을 명확하게 관리할 수 있어 가독성이 높음
단점:
- 코드가 길어질 수 있으며, 메뉴가 많아질 경우 관리가 복잡해질 수 있음
- 새로운 메뉴 아이템을 추가할 때 여러 개의 코드를 수정해야할 수도 있음
결론
메뉴 아이템의 구조를 개선하는 방법을 고민하게 되었습니다. 분리된 접근 방식은 각 메뉴 아이템의 정보를 명확히 확인할 수 있어 유용했지만, 코드의 길이가 길어지는 단점도 있었습니다. 반면, 통합된 접근 방식은 중복을 줄여 코드 유지보수에 유리했으나, 가독성이 떨어지는 단점이 있었습니다.
이 포스트를 작성하며 좋은 코드란 이 포스트를 작성하며 좋은 코드란 단순히 코드의 중복을 줄이는 것이 아니라, 코드를 읽는 사람이 쉽게 이해할 수 있어야 한다는 것을 깨달았습니다. 앞으로는 이러한 교훈을 바탕으로, 코드의 가독성을 높이고 유지보수를 용이하게 할 수 있는 방법을 지속적으로 고민해야겠습니다.