๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Lect & Tip/node, Angular, React

React JS ๋ฐ์ดํ„ฐํ”ผ์ปค ์ตœ์†Œ/์ตœ๋Œ€ ๋‚ ์งœ ์„ค์ • ๊ฐ€์ด๋“œ

by st๊ณต๊ฐ„ 2025. 2. 12.

๋ชฉ์ฐจ

    React JS ๋ฐ์ดํ„ฐํ”ผ์ปค ์ตœ์†Œ/์ตœ๋Œ€ ๋‚ ์งœ ์„ค์ • ๊ฐ€์ด๋“œ

    ์ตœ๊ทผ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์—์„œ ์‚ฌ์šฉ์ž ์นœํ™”์ ์ธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ์ค‘์š”ํ•œ ์š”์†Œ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋‚ ์งœ ์„ ํƒ ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค. React๋ฅผ ๋น„๋กฏํ•œ ์ตœ์‹  ํ”„๋ก ํŠธ์—”๋“œ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ๋Š” ๋‹ค์–‘ํ•œ ๋‚ ์งœ ์„ ํƒ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žˆ์œผ๋ฉฐ, ๊ทธ ์ค‘์—์„œ๋„ JavaScript ๊ธฐ๋ฐ˜์˜ ๋ฐ์ดํ„ฐํ”ผ์ปค๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์›ํ•˜๋Š” ๋‚ ์งœ ๋ฒ”์œ„๋ฅผ ์†์‰ฝ๊ฒŒ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค๋‹ˆ๋‹ค.

    ์˜ค๋Š˜์€ React์—์„œ JS ๋ฐ์ดํ„ฐํ”ผ์ปค๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ตœ์†Œ ๋‚ ์งœ์™€ ์ตœ๋Œ€ ๋‚ ์งœ๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์ž์„ธํ•˜๊ฒŒ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

    ๋ฐ์ดํ„ฐํ”ผ์ปค์˜ ํ•„์š”์„ฑ๊ณผ ๊ธฐ๋ณธ ๊ฐœ๋…

    ์›น ํผ์ด๋‚˜ ์˜ˆ์•ฝ ์‹œ์Šคํ…œ, ์ผ์ • ๊ด€๋ฆฌ ๋“ฑ ์—ฌ๋Ÿฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ ๋‚ ์งœ ์„ ํƒ ๊ธฐ๋Šฅ์€ ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค. ๋‹จ์ˆœํžˆ ์‚ฌ์šฉ์ž๊ฐ€ ์ž„์˜์˜ ๋‚ ์งœ๋ฅผ ์ž…๋ ฅํ•˜๋„๋ก ๋‘๋Š” ๋Œ€์‹ , ๋ฏธ๋ฆฌ ์ •ํ•ด์ง„ ๋ฒ”์œ„ ๋‚ด์—์„œ ๋‚ ์งœ๋ฅผ ์„ ํƒํ•˜๋„๋ก ์ œํ•œํ•จ์œผ๋กœ์จ ๋ฐ์ดํ„ฐ์˜ ์ •ํ™•์„ฑ์„ ๋†’์ด๊ณ  ์‚ฌ์šฉ์ž ์‹ค์ˆ˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐํ”ผ์ปค ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ด์šฉํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์žฅ์ ์„ ๋ˆ„๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    • ์‚ฌ์šฉ์ž ํŽธ์˜์„ฑ: ์บ˜๋ฆฐ๋” UI๋ฅผ ํ†ตํ•ด ์ง๊ด€์ ์œผ๋กœ ๋‚ ์งœ๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ ํ™•๋ณด: ๋ฏธ๋ฆฌ ์ง€์ •ํ•œ ์ตœ์†Œ/์ตœ๋Œ€ ๋‚ ์งœ ๋ฒ”์œ„ ๋‚ด์—์„œ๋งŒ ์„ ํƒ์ด ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ์ž˜๋ชป๋œ ๋ฐ์ดํ„ฐ ์ž…๋ ฅ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    • ์œ ์—ฐํ•œ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•: ๋‹ค์–‘ํ•œ ์„ค์ • ์˜ต์…˜์„ ํ†ตํ•ด ํŠน์ • ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž์ถฐ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ํŠนํžˆ React์—์„œ๋Š” ์—ฌ๋Ÿฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์กด์žฌํ•˜์ง€๋งŒ, ๊ทธ ์ค‘์—์„œ๋„ react-datepicker ๊ฐ™์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ์‚ฌ์šฉ์ด ๊ฐ„ํŽธํ•˜๊ณ  ์ปค๋ฎค๋‹ˆํ‹ฐ ์ง€์›์ด ํ™œ๋ฐœํ•˜์—ฌ ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

    React์—์„œ ๋ฐ์ดํ„ฐํ”ผ์ปค ์‚ฌ์šฉํ•˜๊ธฐ

    React ํ™˜๊ฒฝ์—์„œ ๋ฐ์ดํ„ฐํ”ผ์ปค๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์šฐ์„  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ž„ํฌํŠธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” react-datepicker ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์˜ˆ์‹œ๋กœ ์‚ฌ์šฉํ•œ ์„ค์น˜ ๋ฐ ๊ธฐ๋ณธ ์‚ฌ์šฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

    import React, { useState } from "react";
    import DatePicker from "react-datepicker";
    import "react-datepicker/dist/react-datepicker.css";
    
    const MyDatePicker = () => {
      const [startDate, setStartDate] = useState(new Date());
    
      return (
        <div>
          <DatePicker
            selected={startDate}
            onChange={(date) => setStartDate(date)}
          />
        </div>
      );
    };
    
    export default MyDatePicker;

    ์œ„ ์˜ˆ์ œ๋Š” ๊ธฐ๋ณธ์ ์ธ ๋‚ ์งœ ์„ ํƒ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๊ฐ€ ์บ˜๋ฆฐ๋”์—์„œ ๋‚ ์งœ๋ฅผ ์„ ํƒํ•˜๋ฉด startDate ์ƒํƒœ๊ฐ€ ์—…๋ฐ์ดํŠธ๋ฉ๋‹ˆ๋‹ค. ์ด์ฒ˜๋Ÿผ ๊ฐ„๋‹จํ•œ ๊ตฌ์„ฑ์„ ํ†ตํ•ด ๋‚ ์งœ ์„ ํƒ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์ตœ์†Œ ๋‚ ์งœ์™€ ์ตœ๋Œ€ ๋‚ ์งœ ์„ค์ •ํ•˜๊ธฐ

    ํŠน์ • ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ๋‚ ์งœ ๋ฒ”์œ„๋ฅผ ์ œํ•œํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์˜ˆ์•ฝ ์‹œ์Šคํ…œ์—์„œ๋Š” ์˜ค๋Š˜ ๋‚ ์งœ ์ดํ›„์˜ ๋‚ ์งœ๋งŒ ์˜ˆ์•ฝํ•˜๋„๋ก ์ œํ•œํ•˜๊ฑฐ๋‚˜, ์ด๋ฒคํŠธ ๋“ฑ๋ก์˜ ๊ฒฝ์šฐ ํŠน์ • ๊ธฐ๊ฐ„ ๋‚ด์˜ ๋‚ ์งœ๋งŒ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด react-datepicker ์ปดํฌ๋„ŒํŠธ๋Š” minDate์™€ maxDate ์†์„ฑ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

    ์•„๋ž˜ ์ฝ”๋“œ๋Š” ์ตœ์†Œ ๋‚ ์งœ๋ฅผ ์˜ค๋Š˜ ๋‚ ์งœ๋กœ, ์ตœ๋Œ€ ๋‚ ์งœ๋ฅผ ์˜ค๋Š˜๋กœ๋ถ€ํ„ฐ 30์ผ ํ›„๋กœ ์„ค์ •ํ•˜๋Š” ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

    import React, { useState } from "react";
    import DatePicker from "react-datepicker";
    import "react-datepicker/dist/react-datepicker.css";
    
    const LimitedDatePicker = () => {
      const [selectedDate, setSelectedDate] = useState(new Date());
    
      // ์˜ค๋Š˜ ๋‚ ์งœ๋ฅผ ์ตœ์†Œ ๋‚ ์งœ๋กœ ์„ค์ •
      const minDate = new Date();
    
      // ์˜ค๋Š˜ ๋‚ ์งœ๋กœ๋ถ€ํ„ฐ 30์ผ ํ›„๋ฅผ ์ตœ๋Œ€ ๋‚ ์งœ๋กœ ์„ค์ •
      const maxDate = new Date();
      maxDate.setDate(maxDate.getDate() + 30);
    
      return (
        <div>
          <DatePicker
            selected={selectedDate}
            onChange={(date) => setSelectedDate(date)}
            minDate={minDate}
            maxDate={maxDate}
            placeholderText="๋‚ ์งœ๋ฅผ ์„ ํƒํ•˜์„ธ์š”"
          />
        </div>
      );
    };
    
    export default LimitedDatePicker;

    ์ด ์˜ˆ์ œ์—์„œ minDate์™€ maxDate ์†์„ฑ์„ ์ง€์ •ํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋Š” ๋‚ ์งœ ๋ฒ”์œ„๋ฅผ ์ œํ•œํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋‚ ์งœ ๋ฒ”์œ„ ์ œํ•œ์„ ํ†ตํ•ด ์˜ˆ์•ฝ์ด๋‚˜ ์ด๋ฒคํŠธ ๋“ฑ๋ก ๋“ฑ ๋‹ค์–‘ํ•œ ์‹œ๋‚˜๋ฆฌ์˜ค์—์„œ ์‚ฌ์šฉ์ž์˜ ์ž…๋ ฅ์„ ๋ณด๋‹ค ์ •ํ™•ํ•˜๊ฒŒ ์ œ์–ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์ตœ์†Œ/์ตœ๋Œ€ ๋‚ ์งœ ์„ค์ •์˜ ํ™œ์šฉ ์˜ˆ์‹œ

    ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋‚ ์งœ ๋ฒ”์œ„๋ฅผ ๋™์ ์œผ๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์‚ฌ์šฉ์ž๊ฐ€ ์˜ˆ์•ฝํ•˜๊ณ ์ž ํ•˜๋Š” ๋‚ ์งœ๊ฐ€ ์˜ค๋Š˜ ์ดํ›„ 90์ผ ์ด๋‚ด์—ฌ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ, ์•„๋ž˜์™€ ๊ฐ™์ด ๋™์ ์œผ๋กœ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    import React, { useState } from "react";
    import DatePicker from "react-datepicker";
    import "react-datepicker/dist/react-datepicker.css";
    
    const DynamicDatePicker = () => {
      const [selectedDate, setSelectedDate] = useState(new Date());
    
      // ์˜ค๋Š˜ ๋‚ ์งœ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋™์  ๋ฒ”์œ„ ์„ค์ •
      const today = new Date();
      const minDate = today;
      const maxDate = new Date();
      maxDate.setDate(today.getDate() + 90);
    
      return (
        <div>
          <DatePicker
            selected={selectedDate}
            onChange={(date) => setSelectedDate(date)}
            minDate={minDate}
            maxDate={maxDate}
            dateFormat="yyyy/MM/dd"
          />
        </div>
      );
    };
    
    export default DynamicDatePicker;

    ์ด์ฒ˜๋Ÿผ ์‚ฌ์šฉ์ž์˜ ์š”๊ตฌ ์‚ฌํ•ญ์ด๋‚˜ ํŠน์ • ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ๋”ฐ๋ผ ์ตœ์†Œ ๋‚ ์งœ์™€ ์ตœ๋Œ€ ๋‚ ์งœ๋ฅผ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ๋”์šฑ ์œ ์—ฐํ•œ ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๋˜ํ•œ, ํŠน์ • ๋‚ ์งœ ๋ฒ”์œ„๋ฅผ ๋ฒ—์–ด๋‚˜๋Š” ๋‚ ์งœ๋ฅผ ์„ ํƒํ•˜๋ ค๊ณ  ํ•  ๋•Œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ž๋™์œผ๋กœ ํ•ด๋‹น ๋‚ ์งœ๋ฅผ ๋น„ํ™œ์„ฑํ™”(disabled) ์ฒ˜๋ฆฌํ•ด ์ฃผ๋ฏ€๋กœ, ์‚ฌ์šฉ์ž ์ž…์žฅ์—์„œ๋„ ํ˜ผ๋ž€์„ ์ค„์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์‚ฌ์šฉ ์‹œ ์ฃผ์˜์‚ฌํ•ญ ๋ฐ ํŒ

    ๋ฐ์ดํ„ฐํ”ผ์ปค๋ฅผ ํ™œ์šฉํ•  ๋•Œ ๊ณ ๋ คํ•ด์•ผ ํ•  ๋ช‡ ๊ฐ€์ง€ ์‚ฌํ•ญ๊ณผ ํŒ์„ ์†Œ๊ฐœํ•ฉ๋‹ˆ๋‹ค.

    1. ์‹œ๊ฐ„๋Œ€(Time Zone) ๊ณ ๋ ค:
      ๋‚ ์งœ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๊ฐ„์˜ ์‹œ๊ฐ„๋Œ€ ์ฐจ์ด๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠนํžˆ ๊ธ€๋กœ๋ฒŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ฒฝ์šฐ, ์‚ฌ์šฉ์ž์˜ ๋กœ์ปฌ ์‹œ๊ฐ„๋Œ€์™€ ์„œ๋ฒ„ ์‹œ๊ฐ„๋Œ€๋ฅผ ์ผ์น˜์‹œํ‚ค๊ฑฐ๋‚˜ ์ ์ ˆํ•œ ๋ณ€ํ™˜์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
    2. ๋‚ ์งœ ํ˜•์‹(Date Format) ์ง€์ •:
      ์‚ฌ์šฉ์ž๊ฐ€ ๋‚ ์งœ๋ฅผ ์ž…๋ ฅํ•  ๋•Œ ํ˜ผ๋ž€์ด ์—†๋„๋ก ์ผ๊ด€๋œ ๋‚ ์งœ ํ˜•์‹์„ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. react-datepicker์˜ dateFormat ์†์„ฑ์„ ํ™œ์šฉํ•˜๋ฉด ์›ํ•˜๋Š” ํ˜•์‹์œผ๋กœ ๋‚ ์งœ๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
    3. ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ(Validation):
      ํ”„๋ก ํŠธ์—”๋“œ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๋ฐฑ์—”๋“œ์—์„œ๋„ ๋‚ ์งœ ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ง„ํ–‰ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์ธก์˜ ๋ฐ์ดํ„ฐ ์ œํ•œ์€ ์‚ฌ์šฉ ํŽธ์˜์„ฑ์„ ์œ„ํ•ด ์ œ๊ณต๋˜์ง€๋งŒ, ๋ณด์•ˆ์ด๋‚˜ ๋ฐ์ดํ„ฐ ๋ฌด๊ฒฐ์„ฑ์„ ์œ„ํ•ด ์„œ๋ฒ„ ์ธก ๊ฒ€์ฆ์ด ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.
    4. ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค(UI) ๊ณ ๋ ค:
      ์บ˜๋ฆฐ๋” ์ปดํฌ๋„ŒํŠธ์˜ ์Šคํƒ€์ผ์ด๋‚˜ ๋ ˆ์ด์•„์›ƒ์„ ํ”„๋กœ์ ํŠธ์˜ ๋””์ž์ธ ์‹œ์Šคํ…œ์— ๋งž๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•˜๋Š” ๊ฒƒ๋„ ์ค‘์š”ํ•œ ํฌ์ธํŠธ์ž…๋‹ˆ๋‹ค. CSS๋ฅผ ์ง์ ‘ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” ํ…Œ๋งˆ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•ด ๋ณด์„ธ์š”.
    5. ๋ฐ˜์‘ํ˜• ๋””์ž์ธ:
      ๋‹ค์–‘ํ•œ ๋””๋ฐ”์ด์Šค์—์„œ ๋‚ ์งœ ์„ ํƒ ๊ธฐ๋Šฅ์ด ์›ํ™œํ•˜๊ฒŒ ์ž‘๋™ํ•˜๋„๋ก ๋ฐ˜์‘ํ˜• ๋””์ž์ธ์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋ฐ”์ผ ํ™˜๊ฒฝ์—์„œ๋Š” ํ„ฐ์น˜ ์ด๋ฒคํŠธ์— ์ตœ์ ํ™”๋œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
    6. ์ถ”๊ฐ€ ๊ธฐ๋Šฅ ํ™œ์šฉ:
      ์ผ๋ถ€ ๋ฐ์ดํ„ฐํ”ผ์ปค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋‚ ์งœ ๋ฒ”์œ„ ์„ ํƒ, ๋‹ค์ค‘ ๋‚ ์งœ ์„ ํƒ, ์‹œ๊ฐ„ ์„ ํƒ ๋“ฑ ์ถ”๊ฐ€ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ์ ํŠธ์˜ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๊ฒŒ ์ด๋Ÿฌํ•œ ๊ธฐ๋Šฅ๋“ค์„ ํ•จ๊ป˜ ๊ณ ๋ คํ•˜๋ฉด ๋”์šฑ ํ’๋ถ€ํ•œ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ์˜ ๊ตฌํ˜„ ๋ฐ ํ™•์žฅ

    ์‹ค์ œ ๊ฐœ๋ฐœ ํ˜„์žฅ์—์„œ๋Š” ๋‹จ์ˆœํžˆ ์ตœ์†Œ ๋‚ ์งœ์™€ ์ตœ๋Œ€ ๋‚ ์งœ๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์„ ๋„˜์–ด์„œ, ์‚ฌ์šฉ์ž ์ธํ„ฐ๋ž™์…˜์— ๋”ฐ๋ผ ๋‚ ์งœ ๋ฒ”์œ„๋ฅผ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ํŠน์ • ์ด๋ฒคํŠธ์˜ ๋“ฑ๋ก ๊ธฐ๊ฐ„์ด ๋ณ€๊ฒฝ๋˜๊ฑฐ๋‚˜, ์‚ฌ์šฉ์ž์˜ ์„ ํƒ์— ๋”ฐ๋ผ ์˜ˆ์•ฝ ๊ฐ€๋Šฅํ•œ ๋‚ ์งœ๊ฐ€ ๋‹ฌ๋ผ์ง€๋Š” ์ƒํ™ฉ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์€ ๋กœ์ง์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    import React, { useState, useEffect } from "react";
    import DatePicker from "react-datepicker";
    import "react-datepicker/dist/react-datepicker.css";
    
    const EventDatePicker = ({ eventStartDate, eventEndDate }) => {
      const [selectedDate, setSelectedDate] = useState(new Date());
      const [minDate, setMinDate] = useState(new Date());
      const [maxDate, setMaxDate] = useState(new Date());
    
      useEffect(() => {
        // ์ด๋ฒคํŠธ ์‹œ์ž‘ ๋‚ ์งœ์™€ ์ข…๋ฃŒ ๋‚ ์งœ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์ตœ์†Œ/์ตœ๋Œ€ ๋‚ ์งœ ์„ค์ •
        if (eventStartDate && eventEndDate) {
          setMinDate(new Date(eventStartDate));
          setMaxDate(new Date(eventEndDate));
        }
      }, [eventStartDate, eventEndDate]);
    
      return (
        <div>
          <DatePicker
            selected={selectedDate}
            onChange={(date) => setSelectedDate(date)}
            minDate={minDate}
            maxDate={maxDate}
            dateFormat="yyyy/MM/dd"
          />
        </div>
      );
    };
    
    export default EventDatePicker;

    ์œ„ ์ฝ”๋“œ๋Š” ์ด๋ฒคํŠธ์˜ ์‹œ์ž‘๊ณผ ์ข…๋ฃŒ ๋‚ ์งœ๋ฅผ ๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ๋กœ๋ถ€ํ„ฐ ๋ฐ›์•„ ํ•ด๋‹น ๋ฒ”์œ„ ๋‚ด์—์„œ ๋‚ ์งœ๋ฅผ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•œ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค. ์ด์™€ ๊ฐ™์ด ๋™์ ์ธ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ†ตํ•ด ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์— ๋งž๊ฒŒ ๋ฐ์ดํ„ฐํ”ผ์ปค๋ฅผ ์œ ์—ฐํ•˜๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๋˜ํ•œ, ๋ณต์žกํ•œ ๋‚ ์งœ ๊ณ„์‚ฐ์ด๋‚˜ ์กฐ๊ฑด๋ถ€ ๋กœ์ง์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” moment.js, date-fns์™€ ๊ฐ™์€ ๋‚ ์งœ ์ฒ˜๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ํ–ฅ์ƒ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, date-fns์˜ ๊ฒฝ์šฐ ์•„๋ž˜์™€ ๊ฐ™์ด ๋‚ ์งœ ๊ณ„์‚ฐ์„ ๊ฐ„ํŽธํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    import { addDays, format } from "date-fns";
    
    const today = new Date();
    const futureDate = addDays(today, 30);
    console.log("์˜ค๋Š˜ ๋‚ ์งœ:", format(today, "yyyy/MM/dd"));
    console.log("30์ผ ํ›„:", format(futureDate, "yyyy/MM/dd"));

    ์ด์ฒ˜๋Ÿผ ๋‚ ์งœ ์—ฐ์‚ฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋ณด๋‹ค ๋ณต์žกํ•œ ๋‚ ์งœ ๊ณ„์‚ฐ์ด๋‚˜ ํฌ๋งท ๋ณ€ํ™˜์ด ์šฉ์ดํ•ด์ ธ, ๋ฐ์ดํ„ฐํ”ผ์ปค์™€์˜ ์—ฐ๋™๋„ ๋ณด๋‹ค ์›ํ™œํ•˜๊ฒŒ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ์—๋Ÿฌ ์ฒ˜๋ฆฌ ๋ฐ ๋””๋ฒ„๊น… ํŒ

    ๋ฐ์ดํ„ฐํ”ผ์ปค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ณผ์ •์—์„œ ์ข…์ข… ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ์—๋Ÿฌ ์ƒํ™ฉ์— ๋Œ€๋น„ํ•˜๋Š” ๊ฒƒ๋„ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. ๋ช‡ ๊ฐ€์ง€ ์ฃผ์˜ํ•ด์•ผ ํ•  ์ ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    • ์ž˜๋ชป๋œ ๋‚ ์งœ ํ˜•์‹:
      ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ๋‚ ์งœ๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ, ์ž˜๋ชป๋œ ํ˜•์‹์˜ ์ž…๋ ฅ์œผ๋กœ ์ธํ•ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋•Œ๋Š” ์ž…๋ ฅ๊ฐ’์— ๋Œ€ํ•œ ์ •๊ทœํ‘œํ˜„์‹ ๊ฒ€์ฆ์ด๋‚˜, ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋‚ด์žฅ ๊ธฐ๋Šฅ์„ ํ™œ์šฉํ•ด ํ˜•์‹์„ ๊ฐ•์ œํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.
    • ์ƒํƒœ ์—…๋ฐ์ดํŠธ ๋ฌธ์ œ:
      React์˜ ์ƒํƒœ ๊ด€๋ฆฌ์—์„œ ๋น„๋™๊ธฐ ์—…๋ฐ์ดํŠธ๋กœ ์ธํ•ด ๋‚ ์งœ ๊ฐ’์ด ์˜๋„ํ•œ ๋Œ€๋กœ ๋ฐ˜์˜๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ, ์ƒํƒœ ์—…๋ฐ์ดํŠธ ํ›„ ์ฝ˜์†” ๋กœ๊ทธ๋‚˜ ๋””๋ฒ„๊น… ํˆด์„ ํ™œ์šฉํ•ด ๊ฐ’์ด ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋ณ€๊ฒฝ๋˜๋Š”์ง€ ํ™•์ธํ•ด ๋ณด์„ธ์š”.
    • ์ปดํฌ๋„ŒํŠธ ์žฌ๋ Œ๋”๋ง:
      ๋‚ ์งœ ๋ฒ”์œ„๊ฐ€ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝ๋  ๋•Œ, ๋ถˆํ•„์š”ํ•œ ์žฌ๋ Œ๋”๋ง์œผ๋กœ ์„ฑ๋Šฅ ์ด์Šˆ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฉ”๋ชจ์ด์ œ์ด์…˜ ๊ธฐ๋ฒ•์ด๋‚˜ React์˜ ์ตœ์ ํ™” ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•ด ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๋งˆ๋ฌด๋ฆฌ ๋ฐ ๊ฒฐ๋ก 

    React๋ฅผ ์‚ฌ์šฉํ•œ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ฐœ๋ฐœ์—์„œ JS ๋ฐ์ดํ„ฐํ”ผ์ปค๋Š” ์‚ฌ์šฉ์ž ์นœํ™”์ ์ธ ๋‚ ์งœ ์„ ํƒ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ๋งค์šฐ ์œ ์šฉํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์ตœ์†Œ ๋‚ ์งœ์™€ ์ตœ๋Œ€ ๋‚ ์งœ ์„ค์ • ๊ธฐ๋Šฅ์€ ์˜ˆ์•ฝ ์‹œ์Šคํ…œ, ์ด๋ฒคํŠธ ๋“ฑ๋ก, ์ผ์ • ๊ด€๋ฆฌ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ถ„์•ผ์—์„œ ๋ฐ์ดํ„ฐ์˜ ์ •ํ™•์„ฑ์„ ๋ณด์žฅํ•˜๊ณ  ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๊ฐœ์„ ํ•˜๋Š” ๋ฐ ํฐ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋Š˜ ์†Œ๊ฐœํ•œ ์˜ˆ์ œ์™€ ํŒ๋“ค์„ ์ฐธ๊ณ ํ•˜์—ฌ, ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ๋งž๊ฒŒ ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•˜๊ณ  ํ™•์žฅํ•ด ๋ณด์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

    ํŠนํžˆ, ์‚ฌ์šฉ์ž ์ธํ„ฐํŽ˜์ด์Šค์™€ ๋ฐ์ดํ„ฐ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ๋™์‹œ์— ๊ณ ๋ คํ•œ ๊ตฌํ˜„ ๋ฐฉ์‹์€ ๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ๋ฌธ์ œ๋ฅผ ์‚ฌ์ „์— ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ, ์™ธ๋ถ€ ๋‚ ์งœ ์ฒ˜๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€์˜ ๊ฒฐํ•ฉ์„ ํ†ตํ•ด ๋ณต์žกํ•œ ๋‚ ์งœ ์—ฐ์‚ฐ๋„ ์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ, ์ด๋Ÿฌํ•œ ๋ถ€๋ถ„๋“ค์„ ์ ๊ทน์ ์œผ๋กœ ํ™œ์šฉํ•˜๋ฉด ๋ณด๋‹ค ์•ˆ์ •์ ์ธ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    ๋งˆ์ง€๋ง‰์œผ๋กœ, ํ•ญ์ƒ ์ตœ์‹  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ๊ธฐ์ˆ  ๋™ํ–ฅ์„ ํ™•์ธํ•˜์—ฌ, ๋ณด์•ˆ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๊ณ ๋ คํ•œ ์ตœ์ ์˜ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค. React ์ปค๋ฎค๋‹ˆํ‹ฐ์˜ ๋‹ค์–‘ํ•œ ์ž๋ฃŒ์™€ ์˜ˆ์ œ๋“ค์„ ์ฐธ๊ณ ํ•˜๋ฉด, ๋”์šฑ ํ’๋ถ€ํ•œ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

    React JS ๋ฐ์ดํ„ฐํ”ผ์ปค๋ฅผ ํ™œ์šฉํ•œ ์ตœ์†Œ ๋‚ ์งœ์™€ ์ตœ๋Œ€ ๋‚ ์งœ ์„ค์ • ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž ์นœํ™”์ ์ด๊ณ  ์•ˆ์ •์ ์ธ ๋‚ ์งœ ์„ ํƒ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ด ๋ณด์‹œ๊ธฐ ๋ฐ”๋ผ๋ฉฐ, ์ด๋ฒˆ ํฌ์ŠคํŒ…์ด ๊ฐœ๋ฐœ์— ๋งŽ์€ ๋„์›€์ด ๋˜๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

    ๋ฐ˜์‘ํ˜•

    ๋Œ“๊ธ€