๐Ÿ’ช React JS์—์„œ ์‚ฌ์šฉ์ž ์ง€์ • ๋ชจ๋‹ฌ/ํŒ์—… ๊ตฌ์„ฑ ์š”์†Œ ๊ตฌ์ถ•

22542 ๋‹จ์–ด javascriptbeginnerscssreact
์ด ๊ฒŒ์‹œ๋ฌผ์—์„œ๋Š” react js๋กœ ์‚ฌ์šฉ์ž ์ •์˜ ๋ชจ๋‹ฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋นŒ๋“œํ•ฉ๋‹ˆ๋‹ค. CSS ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์ฒ˜์Œ๋ถ€ํ„ฐ ์ด Modal ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋นŒ๋“œํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜๋Š” ์ด ํŠœํ† ๋ฆฌ์–ผ์˜ ๋ ๋ถ€๋ถ„์—์„œ ๋นŒ๋“œํ•  ๋ฐ๋ชจ ๐Ÿ˜์ž…๋‹ˆ๋‹ค. ๋งค์šฐ ์•„๋ฆ„๋‹ต๊ณ  ์™„๋ฒฝํ•˜๊ฒŒ ์‚ฌ์šฉ์ž ์ •์˜ํ•  ์ˆ˜ ์žˆ๋Š” Modal ๊ตฌ์„ฑ ์š”์†Œ์ž…๋‹ˆ๋‹ค.



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

  • ์‹ ์„ ํ•œ ๋ฐ˜์‘ ์•ฑ ๋งŒ๋“ค๊ธฐ



    ๋จผ์ € ๋‹ค์Œ ๋ช…๋ น์„ ์‚ฌ์šฉํ•˜์—ฌ create-react-app cli ๋„๊ตฌ์˜ ๋„์›€์œผ๋กœ ์ƒˆ๋กœ์šด ๋ฐ˜์‘ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

    npx create-react-app modal
    

    npm start๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑ๋œ ์•ฑ์„ ์‹œ์ž‘ํ•˜๊ณ  ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์—ด๊ณ  http://localhost:3000๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜์‘์˜ ๊ธฐ๋ณธ ์•ฑ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.
    ์ด์ œ ์‹ค์ œ Modal ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ๋””์ž์ธํ•˜๊ณ  ๋งŒ๋“œ๋Š” ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ๋„˜์–ด ๊ฐ‘์‹œ๋‹ค.

    Modal ์ปดํฌ๋„ŒํŠธ ๋งŒ๋“ค๊ธฐ ๋ฐ ๋””์ž์ธ



    ์ด์ œ ์•ฑ์˜ src ํด๋” ์•ˆ์— ๊ตฌ์„ฑ ์š”์†Œ ํด๋”๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ด ๊ตฌ์„ฑ ์š”์†Œ ํด๋” ์•ˆ์— ๋ชจ๋‹ฌ ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” ํŒŒ์ผModal.js๊ณผ ๋ชจ๋‹ฌ ๊ตฌ์„ฑ ์š”์†Œ์— ๋Œ€ํ•œ css ์Šคํƒ€์ผ์„ ํฌํ•จํ•˜๋Š” ํŒŒ์ผmodal.module.css์ด ์žˆ๋Š” ๋ชจ๋‹ฌ ํด๋”๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

    ๋””์ž์ธ ๋ถ€๋ถ„์œผ๋กœ ๋Œ์•„๊ฐ€์„œ ์•„๋ž˜์— ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

    /* modal.module.css */
    
    .modal__wrap {
        position: fixed;
        display: block;
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        margin: 0 auto;
        top: 0;
        left: 0;
        width: 100vw;
        height: 100vh;
        z-index: 100;
        overflow-x: hidden;
        background-color: rgba(31, 32, 41, .75);
        pointer-events: none;
        opacity: 0;
        transition: opacity 250ms 700ms ease;
    }
    
    .visible {
        pointer-events: auto;
        opacity: 1;
        transition: all 300ms ease-in-out;
    }
    
    .modal {
        overflow-y: scroll;
        overflow-x: hidden;
        position: relative;
        display: block;
        width: 60vw;
        height: 60%;
        min-height: 400px;
        min-width: 400px;
        margin: 0 auto;
        margin-top: 20px;
        margin-bottom: 20px;
        border-radius: 4px;
        padding-bottom: 20px;
        background-color: #fff;
        align-self: center;
        box-shadow: 0 12px 25px 0 rgba(199, 175, 189, .25);
        opacity: 0;
        transform: scale(0.6);
        transition: opacity 250ms 250ms ease, transform 300ms 250ms ease;
        transform: scale(0);
    }
    
    .visible .modal {
        opacity: 1;
        transform: scale(1);
        transition: opacity 250ms 500ms ease, transform 350ms 500ms ease;
    }
    
    


  • .modal__wrap๋Š” ๋ชจ๋‹ฌ์˜ ๋ž˜ํผ ๋ฐ ๋ฐฐ๊ฒฝ์— ๋Œ€ํ•œ ์Šคํƒ€์ผ์„ ์ง€์ •ํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
  • .modal๋Š” ์ดˆ๊ธฐ์— ์ˆจ๊ฒจ์งˆ ์‹ค์ œ ๋ชจ๋‹ฌ ๊ตฌ์„ฑ ์š”์†Œ์˜ ์Šคํƒ€์ผ์„ ๊ฐ€์งˆ ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.
  • .visible ํด๋ž˜์Šค๋Š” ๋ชจ๋‹ฌ์ด ํŽ˜์ด๋“œ ์ธ ๋ฐ ํŽ˜์ด๋“œ ์•„์›ƒ ํšจ๊ณผ์™€ ํ•จ๊ป˜ ํ‘œ์‹œ๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

  • ์ด์ œ Modal ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒ์„ฑํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
    ์•„๋ž˜๋Š” ์ด์— ๋Œ€ํ•œ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์ž…๋‹ˆ๋‹ค.

    //Modal.js
    
    import React, { useEffect, useRef } from 'react';
    import Button from '../button/Button';
    import CloseIcon from '../CloseIcon';
    import styles from './modal.module.css';
    
    const Modal = ({ modalStyle, children, show, onClose, backdropStyle }) => {
        const modalRef = useRef(null);
        useEffect(
            () => {
                if (show) {
                    modalRef.current.classList.add(styles.visible);
                }
                else {
                    modalRef.current.classList.remove(styles.visible);
                }
            },
            [
                show
            ]
        );
        return (
            <React.Fragment>
                <div ref={modalRef} style={backdropStyle} className={`${styles.modal__wrap}`}>
                    <Button
                        onClick={onClose}
                        style={{ width: 60, height: 40, position: 'absolute', top: 0, right: 0, margin: '1rem' }}
                        className={styles.close__btn}
                    >
                        <CloseIcon height="20px" width="20px" className={styles.close__icon} />
                    </Button>
                    <div style={modalStyle} className={styles.modal}>
                        {children}
                    </div>
                </div>
            </React.Fragment>
        );
    };
    
    export default Modal;
    
    


    ์ด ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๋„ค ๊ฐ€์ง€ ์†Œํ’ˆ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
    1. modalStyle - ํ‘œ์‹œ๋˜๋Š” ๋ชจ๋‹ฌ ์ฐฝ์˜ ์Šคํƒ€์ผ์„ ์‚ฌ์šฉ์ž ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • backdropStyle - ๋ชจ๋‹ฌ ์ฐฝ์˜ ๋ฐฐ๊ฒฝ ์Šคํƒ€์ผ์„ ์‚ฌ์šฉ์ž ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • onClose - ๋ชจ๋‹ฌ์„ ๋‹ซ๋Š” ๋…ผ๋ฆฌ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ.
  • show - ๋ชจ๋‹ฌ์ด ์—ด๋ ค ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ถ€์šธ ์†์„ฑ์ž…๋‹ˆ๋‹ค.

  • ์—ฌ๊ธฐ์—์„œ ์ด ๊ตฌ์„ฑ ์š”์†Œ ๋‚ด๋ถ€์— ๋‘ ๊ฐœ์˜ ๊ตฌ์„ฑ ์š”์†ŒButton์™€ CloseIcon์„ ๋” ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. Now Button ๊ตฌ์„ฑ ์š”์†Œ๋Š” ๊ธฐ๋ณธ ์Šคํƒ€์ผ์˜ ๊ฐ„๋‹จํ•œ ๋ฒ„ํŠผ์ž…๋‹ˆ๋‹ค. CloseIcon์€ ๋‹จ์ˆœํžˆ ๋ชจ๋‹ฌ์„ ๋‹ซ๋Š” ์•„์ด์ฝ˜svg์ž…๋‹ˆ๋‹ค.

    ์ด ๊ตฌ์„ฑ ์š”์†Œ์—๋Š” ๋‘ ๊ฐ€์ง€ ์ฃผ์š” ๊ธฐ๋Šฅ ๋ถ€๋ถ„์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋จผ์ € useEffect() ํ›„ํฌ ๋‚ด๋ถ€์—์„œ show prop์ด ์ฐธ์ธ์ง€ ์•„๋‹Œ์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. show๊ฐ€ true ์ธ ๊ฒฝ์šฐ ๊ตฌ์„ฑ ์š”์†Œ์— .visible ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ .visible react hook์˜ ๋„์›€์œผ๋กœ Modal ๊ตฌ์„ฑ ์š”์†Œ์—์„œ useRef() ํด๋ž˜์Šค๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.
  • ์†Œํ’ˆ์— ์˜ํ•ด ์ „๋‹ฌ๋œ ์ฒ˜๋ฆฌ๊ธฐonClose()๋ฅผ CloseIcon ์˜ onClick ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ๊ธฐ์— ์ถ”๊ฐ€ํ•˜์—ฌ ํด๋ฆญ ์‹œ ๋ชจ๋‹ฌ์ด ๋‹ซํžˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

  • ๋ชจ๋‹ฌ์„ ํ‘œ์‹œํ•˜๋Š” ์ด๋ฒคํŠธ๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ๋ฒ„ํŠผ



    ๊ฐ„๋‹จํžˆ ํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜์™€ ๊ฐ™์ด App.js ํŒŒ์ผ์— Button์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

    
    //App.js
    
    import React, { useState } from 'react';
    import './App.css';
    import Button from './components/button/Button';
    import Modal from './components/modal/Modal';
    
    function App() {
        const [
            show,
            setShow
        ] = useState(false);
        return (
            <React.Fragment>
                <div style={{ display: 'flex', justifyContent: 'center', alignItems: 'center', height: '100vh' }}>
                    <Button onClick={() => setShow(true)}>Open Modal</Button>
                </div>
                <Modal show={show} onClose={() => setShow(false)}>
                    <div className="content">
                        <img src="https://cdn.pixabay.com/photo/2015/01/09/11/11/office-594132__340.jpg" alt="Developer" />
                        <div className="text">
                            <h2>John Doe</h2>
                            <p>
                                Lorem ipsum dolor sit amet consectetur adipisicing elit. Saepe aliquid placeat omnis
                                adipisci dolores quae amet mollitia sint, temporibus eum magnam facilis odio ex incidunt?
                                Deleniti quam et rem obcaecati. Laborum atque odit expedita nulla.
                            </p>
                            <p>
                                Lorem ipsum dolor sit amet consectetur adipisicing elit. Expedita labore laborum, assumenda
                                dolorum provident quod itaque earum, officia in placeat dignissimos nostrum? Totam corrupti
                                nihil repudiandae ducimus atque quod eos!
                            </p>
                        </div>
                    </div>
                </Modal>
            </React.Fragment>
        );
    }
    
    export default App;
    
    
    


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

    ์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ