개발자
1번 코드와 2번 코드 중 상황 대처에 유연하고 처음 본 사람조차 쉽게 사용할 수 있을까요? 1번 코드의 경우 컴포넌트 내부에서 UI에서 나타내야하는 값을 로직을 수행 후 사용하는 개념이고 2번 코드의 경우 부모 컴포넌트에서 UI에서 나타내야하는 값을 로직을 수행 후 Props로 넘겨 자식 컴포넌트는 부모에게 받은 값을 그대로 보여주기만 하는 개념입니다.
1//1번 코드
2import dayjs from 'dayjs';
3import React, { useState } from 'react';
4
5interface AdvertisementData {
6 payInfo_startPaidAt?: Date;
7 startDate: Date;
8 periodApply: number;
9 periodAccept: number;
10 periodReview: number;
11 //...etc
12}
13
14//Container.tsx
15const Container = () => {
16 const [state, setState] = useState<AdvertisementData>({
17 payInfo_startPaidAt: new Date(),
18 startDate: new Date(),
19 periodApply: 14,
20 periodAccept: 2,
21 periodReview: 14,
22 });
23
24 return (
25 <>
26 {/* 다른 요소들 */}
27 <Component advertisementData={state} />
28 {/* 다른 요소들 */}
29 </>
30 );
31};
32
33//Component.tsx
34const Component = ({
35 advertisementData,
36}: {
37 advertisementData: AdvertisementData;
38}) => {
39 const startDate = dayjs(
40 advertisementData.payInfo_startPaidAt || advertisementData.startDate
41 );
42 const applicationPeriodStart = startDate.format('MM.DD');
43 const applicationPeriodEnd = startDate
44 .add(advertisementData.periodApply, 'd')
45 .format('MM.DD');
46 const announcementDate = startDate
47 .add(advertisementData.periodApply + advertisementData.periodAccept, 'd')
48 .format('MM.DD');
49 const registrationPeriodEnd = startDate
50 .add(
51 advertisementData.periodApply +
52 advertisementData.periodAccept +
53 advertisementData.periodReview,
54 'd'
55 )
56 .format('MM.DD');
57
58 return (
59 <div>
60 <ul>
61 <li>
62 신청 기간 : {applicationPeriodStart}-{applicationPeriodEnd}
63 </li>
64 <li>발표 날짜 : {announcementDate}</li>
65 <li>
66 제출 기간 : {announcementDate}-{registrationPeriodEnd}
67 </li>
68 </ul>
69 </div>
70 );
71};
72
73//2번 코드
74import dayjs from 'dayjs';
75import React, { useState } from 'react';
76
77interface AdvertisementData {
78 payInfo_startPaidAt?: Date;
79 startDate: Date;
80 periodApply: number;
81 periodAccept: number;
82 periodReview: number;
83 //...etc
84}
85
86//Container.tsx
87const Container = () => {
88 const [state, setState] = useState<AdvertisementData>({
89 payInfo_startPaidAt: new Date(),
90 startDate: new Date(),
91 periodApply: 14,
92 periodAccept: 2,
93 periodReview: 14,
94 });
95
96 const startDate = dayjs(state.payInfo_startPaidAt || state.startDate);
97 const applicationPeriodStart = startDate.format('MM.DD');
98 const applicationPeriodEnd = startDate
99 .add(state.periodApply, 'd')
100 .format('MM.DD');
101 const announcementDate = startDate
102 .add(state.periodApply + state.periodAccept, 'd')
103 .format('MM.DD');
104 const registrationPeriodEnd = startDate
105 .add(state.periodApply + state.periodAccept + state.periodReview, 'd')
106 .format('MM.DD');
107
108 return (
109 <>
110 {/* 다른 요소들 */}
111 <Component
112 applicationPeriodStart={applicationPeriodStart}
113 applicationPeriodEnd={applicationPeriodEnd}
114 announcementDate={announcementDate}
115 registrationPeriodEnd={registrationPeriodEnd}
116 />
117 {/* 다른 요소들 */}
118 </>
119 );
120};
121
122interface ComponentProps {
123 applicationPeriodStart: string;
124 applicationPeriodEnd: string;
125 announcementDate: string;
126 registrationPeriodEnd: string;
127}
128
129//Component.tsx
130const Component = ({
131 applicationPeriodStart,
132 applicationPeriodEnd,
133 announcementDate,
134 registrationPeriodEnd,
135}: ComponentProps) => {
136 return (
137 <div>
138 <ul>
139 <li>
140 신청 기간 : {applicationPeriodStart}-{applicationPeriodEnd}
141 </li>
142 <li>발표 날짜 : {announcementDate}</li>
143 <li>
144 제출 기간 : {announcementDate}-{registrationPeriodEnd}
145 </li>
146 </ul>
147 </div>
148 );
149};
답변 1
구조를 꼭 저렇게 해야 한다면 첫 번째 코드를 기반으로 수정을 권합니다. 컨테이너는 다른 요소도 담고 있기 때문에 컴포넌트 관련된 로직을 처리할 이유가 없습니다. 이는 컴포넌트의 책임입니다. 수정한 컴포넌트 코드는 아래와 같습니다. dayjs 사용하는 부분이 꽤 장황하여 커스텀 훅을 사용해 줍시다. 커스텀 훅으로 따로 빼두면 가독성 상승과 함께 표시 내용 추가시 쉽게 대응할 수 있습니다.
1//Component.tsx
2import { useAdsDate } from "@/hooks/useAdsDate"; // 날짜 처리 로직 -> 커스텀 훅
3
4const Component = ({
5 advertisementData,
6}: {
7 advertisementData: AdvertisementData;
8}) => {
9 const [
10 applicationPeriodStart,
11 applicationPeriodEnd,
12 announcementDate,
13 registrationPeriodEnd,
14 ] = useAdsDate(advertisementData);
15
16 return (
17 <div>
18 <ul>
19 <li>
20 신청 기간 : {applicationPeriodStart}-{applicationPeriodEnd}
21 </li>
22 <li>발표 날짜 : {announcementDate}</li>
23 <li>
24 제출 기간 : {announcementDate}-{registrationPeriodEnd}
25 </li>
26 </ul>
27 </div>
28 );
29};
30
31// hooks/useAdsDate.ts
32import dayjs from "dayjs";
33import { useState } from "react";
34
35export const useAdsDate = (advertisementData: AdvertisementData) => {
36 const startDate = dayjs(
37 advertisementData.payInfo_startPaidAt || advertisementData.startDate
38 );
39 const applicationPeriodStart = startDate.format("MM.DD");
40 const applicationPeriodEnd = startDate
41 .add(advertisementData.periodApply, "d")
42 .format("MM.DD");
43 const announcementDate = startDate
44 .add(
45 advertisementData.periodApply + advertisementData.periodAccept,
46 "d"
47 )
48 .format("MM.DD");
49 const registrationPeriodEnd = startDate
50 .add(
51 advertisementData.periodApply +
52 advertisementData.periodAccept +
53 advertisementData.periodReview,
54 "d"
55 )
56 .format("MM.DD");
57 return [
58 applicationPeriodStart,
59 applicationPeriodEnd,
60 announcementDate,
61 registrationPeriodEnd,
62 ];
63};
지금 가입하면 모든 질문의 답변을 볼 수 있어요!
현직자들의 명쾌한 답변을 얻을 수 있어요.
이미 회원이신가요?
커리어리 AI 봇
GPT가 달아주는 답변입니다.
2024년 02월 05일
2번 코드가 더 유연한 설계 방법일 것입니다. 이유는 다음과 같습니다: 1. **단일 책임 원칙(Single Responsibility Principle)**: 2번 코드는 각 컴포넌트가 하나의 책임만을 가지도록 설계되어 있습니다. `Container` 컴포넌트는 상태 관리와 연산 로직을 담당하고, `Component` 컴포넌트는 UI를 표현하는 역할만 담당합니다. 반면, 1번 코드에서 `Component` 컴포넌트는 상태 조회와 연산 로직, 그리고 UI 표현까지 모두 담당하므로 단일 책임 원칙에 어긋납니다. 2. **재사용성(Reusability)**: 2번 코드의 `Component` 컴포넌트는 props를 통해 받은 값을 그대로 UI에 표현하기 때문에, 다른 부모 컴포넌트에서도 재사용이 가능합니다. 반면, 1번 코드의 `Component` 컴포넌트는 내부적으로 연산 로직을 가지고 있으므로 동일한 로직을 다른 곳에서 재사용하려면 코드 복사가 필요합니다. 3. **읽기 쉽고 유지보수하기 용이함**: 2번 코드는 컴포넌트의 역할이 명확하고 분리되어 있으니, 처음 코드를 보는 사람도 쉽게 이해할 수 있습니다. 또한 각 컴포넌트가 단일 책임 원칙을 따르기 때문에 유지보수도 용이합니다. 결론적으로, 두 번째 방식은 유연성, 재사용성, 가독성, 유지보수성 등 여러 면에서 우위에 있습니다. 이는 리액트의 주요 개념인 "컴포넌트 간의 관심사 분리(Separation of Concerns between Components)"를 잘 보여주는 사례로 볼 수 있습니다.
지금 가입하면 모든 질문의 답변을 볼 수 있어요!