개념정리 - Modal Button 구현 (UI)

Seungmin Shin·2021년 7월 6일
1

코딩 개념정리

목록 보기
22/33

1. Modal?

Modal 이란 사용자의 이목을 끌기 위해 사용하는 화면전환 기법을 의미합니다.

여기서 이목을 끈다는 말은, 반드시 사용자가 보게끔 하는것에 그 의의를 두고 있다는 말이 될겁니다.
어떤 방법으로 이목을 끄는걸까요? 바로 사용자가 한번쯤은 무조건 건드려야 한다는 것입니다.

웹사이트를 방문하다가 어떠한 오류가 뜨거나 사용자에게 뭔가 반드시 전달해야하는 정보가 있을때,
브라우저는 얼럿 등을 통하여 사용자에게 정보를 전달합니다.

이런식으로 말이죠, 사용자는 이 창을 그냥 지나칠 수는 없습니다.
반드시 어떠한 입력을 넣어서 저 창을 닫아야만 브라우저 내의 다른 작업을 할 수가 있을것입니다.
창 내의 엑스박스를 클릭하거나, 확인 또는 취소버튼을 누르는것이겠죠,

이렇게 어떠한 정보전달을 목적으로 사용자의 이목을 끌기위한 표현방식을 Modal 이라고 합니다.

그럼 이 Modal 을 한번 구현해 보죠,

2. Modal 창 구현하기 (Button 형식)

지금부터 Modal 창이 구현되도록 해보겠습니다,
이 창이 뜨기위한 전제조건으로 저는 Button 을 선택했습니다.

Button을 클릭하면 Modal 창이 띄워지고, 창을 클릭하여 사라지게 하는 정도로 구현해보겠습니다.

1) Start React

이 구현은 리액트를 기반으로 진행합니다. 그리고 Styled components 를 사용합니다. (전제조건)

먼저 리액트폴더를 만들고 리액트가 제대로 실행하는지 확인합니다.

잘 실행됩니다, 하지만 저희는 이 창은 필요 없으므로 전부 지우고 흰 바탕이 나오게끔 하겠습니다.

( 이 과정을 알고 있다는 전제하에 생략합니다. )

정리가 완료됬습니다, 이제 구현해보죠.

2) Modal Button 구현하기

Modal 창을 띄우기 위해 필요한 조건인 버튼을 하나 만들어 보겠습니다, 간단하게 만들어 보죠.

같은 폴더에 Modal.js 파일을 생성한 후에 여기에 구현을 하겠습니다.

일단 두가지의 컴포넌트를 제작하고 구현했습니다. ModalContainerModalBtn 입니다.

컴포넌트의 위치를 보면 알 수 있듯이,

  • ModalContainer 는 Modal 을 구현하기 위한 요소들을 전체적으로 잡아주는 컴포넌트입니다.
  • ModalBtn 은 말 그래도 버튼을 제작하기위한 컴포넌트입니다.

이렇게 컴포넌트를 만들어서 App.js 에 import 하여 Modal 컴포넌트를 추가하면

이런 버튼을 구현할 수 있습니다. 이렇게 Modal 창을 띄울때 필요한 버튼 구현이 완료 되었습니다.

3) 이벤트핸들러를 이용한 버튼 활성화 시키기

버튼은 구현이 되었고, 이제 Modal 창을 띄우면 될텐데, 그러려면 일단 버튼이 동작을 해야되겠죠?

CSS에 cursor 를 pointer 로 설정을 해놓아서 버튼에 마우스를 가져다 대면 화살표가 포인터로 바뀌긴 하지만
아직 이벤트핸들러를 구현하지 않았기 때문에 현재의 버튼은 버튼으로서 역할을 하지 못합니다.

이제 버튼을 눌러서 버튼이 눌렸다는것을 표현해줍시다.

우리는 저 버튼에 적혀있는 Open Modal 이라는 텍스트가 버튼을 클릭하면 Open !! 으로 바뀌게 할겁니다.
그리고 계속 클릭을 하면 Open Modal 과 Open !! 을 왔다갔다 하겠죠? 시작해 보겠습니다.

일단은 어떠한 이벤트가 일어나려면 기본값에 변화를 주어야하기 때문에
리액트의 기능 중 useState 를 사용하겠습니다,

const [isOpen, setIsOpen] = useState(false);

이렇게 useState 를 이용해서 초기값 isOpen (false) 과 갱신될 값 setIsOpen 을 만들어 줍니다.

isOpen 의 초기값이 false 이므로 '닫혀있다' 라고 한다면,
클릭하여 열리게 되는 값은 true가 되겠죠? 이렇게 isOpen 의 상태를 변화시켜야 합니다.

isOpen 의 상태는 클릭이라는 이벤트가 발생했을때 상태가 변화됩니다.
그러면 isOpen 의 상태를 변화시키는 이벤트 함수를 만들어보겠습니다.

const openModalHandler = () => {
     setIsOpen(!isOpen);
    }

openModalHandler 라는 이벤트 함수를 만들고 이 함수가 실행됬을때
isOpen 의 갱신값이 할당되는 setIsOpen 에 ! isOpen 을 인자로 넣어 클릭할때마다
isOpen 의 값이 false에서 true 로, true에서 false 로 바꾸도록 합니다.

Q : ! isOpen 말고 true 로 하는것은 안되나요?
A : 넵 , 인자를 true 로 할당하게 되면 한번은 클릭이 되겠지만, 그 이후로는 isOpen의 값이 true로
바뀌기 때문에 두번째 클릭부터는 변화가 일어나지 않습니다, 클릭의 목적이 true 로 변하기 위한
단 한번의 시도만 필요하다면 상관없겠지만, 우리는 false 와 true 를 계속해서 번갈아 가는것이
목적이기때문에 ! isOpen 으로 진행합니다.

useState 와 이벤트함수가 적용된 모습입니다.


4) 컴포넌트에 이벤트핸들러 추가하기

자 이제 우리가 만든 이벤트 핸들러를 컴포넌트에 추가해서 버튼이 활성화되도록 만들어봅시다.

이벤트 핸들러가 필요한 컴포넌트는 당연히 버튼에 해당하는 컴포넌트겠죠?
ModalBtn 컴포넌트에 이벤트 핸들러를 추가해보겠습니다.

return (
     <>
     <ModalContainer>
         <ModalBtn onClick = {openModalHandler}>
            Open Modal
         </ModalBtn>
     </ModalContainer>
     </>
    ) 

추가하는것은 간단하죠, 이제 이 버튼은 클릭이 되면 isOpen 의 상태를 변화시킬 수 있게 됬습니다.

하지만 우리는 아직 이 버튼이 제대로 작동하는지 확인할 수 없습니다,
console.log()를 하면 쉽게 알 수 있지만, 우리는 처음에 isOpen의 상태가 바뀐다면
버튼에 쓰여져 있는 Open Modal 이란 텍스트를 Open !! 으로 바꾸기로 했습니다,
텍스트가 바뀐다는것이 바로 상태가 변화했단 의미니까요, 그걸 구현해보도록 하겠습니다.

여기선 조건식이 필요합니다, 상태에 따라 텍스트가 변화해야 하니까요,
if문도 있지만 여기서는 삼항연산자를 사용해보도록 하겠습니다.

{isOpen === false ? 'Open Modal' : 'Open !!'}

이 조건식의 의미는 아시죠? isOpen 이 false 인경우에 'Open Modal' 을 출력하고,
isOpen 이 true 인 경우에는 'Open !!' 을 출력하라는 뜻입니다.

이것을 어디에 적용하느냐? 버튼에 해당하니까 버튼 컴포넌트 안에 넣어줘야겠죠?

안쪽에 작성되어있는 Open Modal 을 지우고 이 코드를 추가하겠습니다.

return (
     <>
     <ModalContainer>
         <ModalBtn onClick = {openModalHandler}>
          {isOpen === false ? 'Open Modal' : 'Open !!'}
         </ModalBtn>
     </ModalContainer>
     </>
    ) 

그리고 나서 버튼이 어떻게 구현되는지 보겠습니다.

클릭을 했을때 Open !! 으로 잘 구현된걸 볼 수 있습니다. (gif 만들기 귀찮아서 안할것임.)

5) Modal 창 띄우기

이제 버튼은 잘 동작을 합니다, 그럼 이제 이 동작하는 버튼을 이용해서 Modal 창을 띄워보도록 합시다.

Modal 창은 버튼처럼 항상 구현되어 있지 않습니다, 버튼을 클릭했을때만 구현이 되야합니다.
일단은 Modal 창의 CSS 를 작성해보겠습니다. 간단하게 만들어보죠.

export const Modalview = styled.div`
  border-radius: 10px;
  background-color: #ecb0bd;
  width: 300px;
  height: 100px;
`

창을 만들었지만, 아직은 뜨지 않을겁니다, 왜냐구요? 뜰 수 있게 구현을 안했으니까요.
이제 구현을 해보겠습니다, 이번에도 조건식이 필요합니다, 창이 뜨기위한 조건이 필요하다고 했죠.

바로 ' 버튼을 클릭했을경우에만 ' 입니다. 이것을 토대로 조건식을 만들어보겠습니다.

{
  isOpen === true ?
    <Modalview>
      Modal 창이 열렸습니다 !!
    </Modalview>
     : null
 }

isOpen 이 true 라는 것은, 버튼이 클릭 되었다는 뜻입니다, 그랬을 경우에 위에서 만든
Modalview 를 출력하고, 그 안에 창이 열렸다는 텍스트를 하나 넣어보겠습니다.

그리고 또 잘 동작하는지 버튼을 클릭해 보겠습니다,

음...일단은 잘 열리긴 했는데 좀 어설프긴 합니다, 이번 개념정리는 이쁘게 만드는것이 아니라
기능구현에 중점을 두고 있으니 넘어가도록 합니다. ( 맘먹으면 잘함 )

이렇게 Modal 창까지 띄우는것이 끝났습니다. 자 고생하셨습니다.

6) 극단적인 Modal 창 만들기

...은 무슨, 아직 안끝났습니다. 이건 제대로 구현한 Modal 이 아닙니다. 아까 맨 처음에
설명한 Modal 의 특징은 사용자가 반드시 건드릴 수 밖에 없다 는 것이었는데, 이 Modal 창은
뭔가 2% 부족합니다, 처음 버튼을 눌러서 Modal 창을 띄웠다면, 우리는 어찌됬든
저 Modal 창 안에서 창을 끄던가 해야되는데, 이 Modal 창 자체에는 아무런 기능이 없고
버튼을 다시 눌러야 Modal 창이 꺼집니다. 이것은 우리가 원하는 Modal 이 아닙니다.

그래서 저는 극단적인 선택을 할겁니다, 버튼을 클릭하면 Modal 창 안에서가 아니면
절대로 밖으로 나갈 수 없게 할겁니다, 그러기 위해선 Modalview 바깥에 하나의 컴포넌트를 추가해야 합니다.
바로 '배경' 의 개념입니다, 버튼과 같은 차원에 있던 Modal 창에 배경을 한겹 더 추가함으로써
한 차원 더 들어간 상태가 되어 버튼과 분리가 될겁니다. 그럼 Modal 창이 활성화 되었을때는
버튼에 접근할 수 없을겁니다. 구현해 봅시다.

export const ModalBackground = styled.div`
 position: fixed;
 z-index: 1;
 top: 0;
 left: 0;
 right: 0;
 bottom: 0;
 background-color: rgba(0,0,0,0.4);
 display: grid;
 align-items: center;
 justify-items: center;
`;

위의 코드를 간단하게 설명하자면
position 으로 배경을 전체적으로 고정시키고
z-index 로 레이어의 높이를 한단계 높입니다.
그리고 두가지 itens 로 배경 컴포넌트 내부의 컴포넌트를 정렬합니다.

이렇게 코드를 작성하고 컴포넌트에 적용시켜 보겠습니다.

return (
     <>
     <ModalContainer>
         <ModalBtn onClick = {openModalHandler}>
            {isOpen === false ? 'Open Modal' : 'Open !!'}
         </ModalBtn>
         {
             isOpen === true ?
             <ModalBackdrop>   // 추가
             <Modalview>
                 Modal 창이 열렸습니다 !!
             </Modalview>
             </ModalBackdrop>  // 추가
             : null
         }
     </ModalContainer>
     </>
    ) 

이렇게 작성하고 다시 버튼을 클릭해보면

배경이 깔리고 그 위로 Modal 창이 뜹니다, 그리고 어디를 클릭해도 Modal 창은 닫히지 않습니다.
버튼을 누를 수도 없게 되었습니다, 극단적으로 우리는 Modal 창을 마주할 수 밖에 없게 된것입니다.

하지만 이 창을 계속 보고만 있을수는 없죠, 뭔가 나갈 수 있는 출구가 있어야 합니다.
닫기버튼을 만들어 창을 닫을 수 있게 해보겠습니다.

7) Modal 창 닫기

창을 닫기위해선 닫기버튼이 있어야겠죠, Modal 창 내부에 닫기버튼을 만들고
그 버튼을 클릭해서 창을 닫아보겠습니다.

일단 창을 닫기위한 버튼은 Modalview 컴포넌트 내부에 작성이 되야할겁니다,
그래야 창 내부에 구현이 될테니까요,

return (
     <>
     <ModalContainer>
         <ModalBtn onClick = {openModalHandler}>
            {isOpen === false ? 'Open Modal' : 'Open !!'}
         </ModalBtn>
         {
             isOpen === true ?
             <ModalBackdrop> 
             <Modalview>
                 Modal 창이 열렸습니다 !!
             </Modalview>
             </ModalBackdrop> 
             : null
         }
     </ModalContainer>
     </>
    ) 

현재 작성되어 있는 코드는 이렇습니다, 그럼 저 'Modal 창이 열렸습니다!!' 아래에 닫기버튼을 만들어보겠습니다.
아, 그 전에 Modal 창이 열렸습니다!! 텍스트는 p태그로 묶어주겠습니다, 그렇지 않으면
텍스트와 버튼이 분리되지 않을테니까요.

return (
     <>
     <ModalContainer>
         <ModalBtn onClick = {openModalHandler}>
            {isOpen === false ? 'Open Modal' : 'Open !!'}
         </ModalBtn>
         {
             isOpen === true ?
             <ModalBackdrop>   
             <Modalview>
                 <p>Modal 창이 열렸습니다 !!</p>  // p태그로 묶어주었다.
                 <button>닫기</button>         // 닫기버튼 생성.
             </Modalview>
             </ModalBackdrop>
             : null
         }
     </ModalContainer>
     </>
    )

이렇게 닫기 버튼을 만들고 한번 봐보겠습니다.

귀염뽀짝한 닫기버튼이 만들어졌습니다, 다시한번 말하지만 이번 개념정리는 기능구현에 집중을....

어쨌든, 닫기 버튼을 만들었는데 동작을 할까요?

네, 안합니다 (ㅋㅋㅋㅋㅋ) 왜냐하면 버튼에 이벤트 핸들러가 없기때문이죠,
이벤트핸들러를 추가하겠습니다, 아까 만들어 놓은 openModalHandler 함수를 이용하면 됩니다.

버튼을 눌렀을때, isOpen의 상태가 변경되어 true 에서 false 상태가 된다면
Modal 창이 사라질겁니다. 그렇게 구현해 보도록 하겠습니다.

 return (
    <>
    <ModalContainer>
        <ModalBtn onClick = {openModalHandler}>
           {isOpen === false ? 'Open Modal' : 'Open !!'}
        </ModalBtn>
        {
            isOpen === true ?
            <ModalBackdrop>   
            <Modalview>
                <p>Modal 창이 열렸습니다 !!</p>
                <button onClick ={openModalHandler}>닫기</button>
            </Modalview>
            </ModalBackdrop>
            : null
        }
    </ModalContainer>
    </>
   ) 

자 이렇게 버튼에 클릭 이벤트까지 추가 했으니 잘 동작할겁니다, 확인해 봅시다.

잘 동작 합니다 (gif 만들기 귀찮다고, 잘 동작합니다. 날 믿으셈)

3. 마무리

Modal 창을 구현하기 위해서 버튼을 제작하고, 버튼을 클릭할 수 있는 이벤트 함수를 만들고
버튼이 클릭되었을때 구현되는 Modal창을 만들어봤습니다.

Modal 창의 특성상 사용자의 이목을 끌어야 하고, 사용자가 다른곳에 한눈팔지 않고
Modal 창이 띄워졌을때는 무조건적으로 Modal 창을 보고 그 안에서 창을 닫을 수 있게 구현하는것이
제대로 된 Modal 의 구현이지 않을까 싶습니다

이상 간단한 UI Components 구현하기 - Modal button 편이었습니다.

profile
Frontend Developer

0개의 댓글