Today Sangmin Learned
article thumbnail
728x90

클론코딩 강의를 들으면서 점점 구조가 복잡해지고, 어려워지고 있음을 몸소 느끼고 있다. 오늘 배운 부분은, 실제 Slack에서 워크스페이스를 API통신을 활용하여 만드는 것이다.

 

이런 거?

우선 시작하기에 앞서 스타일링은 전부 Slack의 개발자도구에서 그대로 가져온 것이므로, 따로 말할 게 없다는 점을 밝힌다. styled-components를 사용하긴 했지만, 이마저도 결국 뭐 직접 짠 거는 아니니까.. 그냥 그러려니 하면 될 것 같다. 사실 중요하지도 않고.

 

간단해 보이지만, 이것을 만들기 위해서는 많은 함수가 필요하다. + 버튼을 눌렀을 때 모달을 불러오는 것이라든지, 모달의 우측상단 X 버튼을 눌렀을 때 모달이 꺼지는 것이라든지.. 우선 페이지와 컴포넌트로 나눠서 설명을 해야할 것 같다.

 

1. 컴포넌트

이 컴포넌트는 껍데기(1행 CloseModalButton, CreateModal)는 제외하고 온전히 기능에만 집중한다. 짧게 설명하면 CreateModal은 이것들을 전부 포함한 전체 화면과 내부 div에 대한 스타일링이고, CloseModalButton은 이 모달을 끄기 위한 버튼 스타일링이다.

 

먼저, TypeScript를 사용하였기 때문에 각 파라미터에 타이핑을 해줘야 한다. 여기서는 Props 인터페이스를 FC<Props>로 불러옴으로써 해결하였다. (FC는 import 문에서도 볼 수 있듯이 React에서 기본적으로 제공하는 것이다.)

  • &times: 알파벳 X보다는 더 깔끔하게 생긴 X자 형태의 버튼이다. 추가 설명은 따로 필요 없을듯
  • onCloseModal & e.stopPropagation(): 모달을 끄는 것인데, 이 부분에 대해서는 아래에서 더 설명하겠다.
  • {children}: 외부 껍데기. 페이지에서 담당한다.
  • show: 페이지에서 띄워주는 것과 관련있다. 이부분은 페이지에서 설명할 것이다.

1-1. onCloseModal & e.stopPropagation()

상기했다시피 onCloseModal은, 인터페이스에서도 볼 수 있듯이 void, 즉 아무것도 반환하지 않는다. 한마디로 그냥 보여지지 않게 하는 것이라고 보면 된다. (어차피 다 그냥 임의로 설정한 변수이다. 이름은 아무 뜻이 없다는 것..)

그리고 e.stopPropagation()은 부모 엘리먼트에게 이벤트 전달을 중단해야 할 때 쓰이는 함수이다. 즉, 현재 onCloseModal은 부모 엘리먼트에 적용되어 있어서 e.stopPropagation()이 없을 경우 내부 div에서도 onCloseModal이 적용되어서 어디를 클릭하든 결국 모달이 꺼지게 되기 때문이다.

e.stopPropagation()을 사용하지 않은 상황인데.. gif를 만들고 보니 마우스가 보이지 않는다. 이 움짤에서 마우스는 X표시가 아닌 아무 곳이나 클릭했다.

즉, e.stopPropagation()을 내부 div에 적용해줌으로써 CreateModal의 내부 div에서는 X 표시를 클릭하지 않는 한 어디를 클릭하든 모달이 꺼지지 않게 되는 것이다.

자매품(?)으로 e.preventDefault()가 있는데, 이는 아래에서 설명하겠다.

 

이제 컴포넌트는 전부 설명했으니, 페이지로 넘어가보자.

 

2. 페이지

다른 부분은 제외하고 오로지 상술한 컴포넌트와 관련한 부분만 가져왔다.

  • 1~5행: 그냥 필요한 것들 가져오는 코드이다. 주목할 부분은 5행의 @components/Modal로 가져왔다는 것, 이것은.. webpack 설정에 기반한 것인데, 여기서 다루기는 너무 길기 때문에 넘어간다. 나중에 따로 포스팅을 할 예정이다.
  • 8행 showCreateWorkspaceModal: 우리가 위에서 다뤘던 컴포넌트를 보여주는지 여부를 결정한다.
  • 9행, 10행: 지난 포스팅에서 다뤘던 useInput custom Hook을 활용하였다. 짧게 다시 얘기하자면, 그냥 input에 입력한 value를 e.target.value로 설정하는 Hook이라고 생각하면 된다. 여기서는, Modal에서 워크스페이스 이름 부분에 쓴 값은 그대로 newWorkspace에 들어가는 것이고, 워크스페이스 URL 부분에 쓴 값은 그대로 newUrl에 들어가는 것이다.
  • 11행 onCreateWorkspace부터는 아래에서 설명한다.

2-1. onCreateWorkspace (useCallback 사용)

여기에서 위에서 말했던 e.preventDefault()가 사용된다.

e.preventDefault()란?

e.preventDefault()는 React에서 정말 많이 쓰인다. 49행에 <form onSubmit={onCreateWorkspace}>...</form> 에서도 볼 수 있듯이 onCreateWorkspace는 submit을 할 때 쓰이는 함수이다. React는 SPA를 지향한다. SPA란 Single Page Application의 약자로, 리프레쉬(새로고침) 없이 한 페이지에서 모든 것을 해결하는 어플리케이션이라는 뜻이다. 그런데, 이러한 submit의 경우 기본적으로 리프레쉬를 수반한다(이는 브라우저의 고유 행동이다). 그렇기 때문에, 이러한 리프레쉬를 막고자 e.preventDefault() 처리를 해줘야 되는 것이다.

 

그리고, Modal에 워크스페이스 이름 부분과 워크스페이스 URL 부분이 빈칸으로 제출되거나 값 없이 공백으로만 제출되는 경우를 막기 위해 14, 15행에서 값이 없거나, 또는 공백을 제거한 값이 아무 것도 없는 경우 아무것도 반환하지 않는 return을 넣었다.

 

그 다음, axios를 통해 미리 세팅되어있던 API를 통해 서버와 통신한다. 서버에는 workspace와 url이 넘어가게 된다. 이 부분은, 각 워크스페이스별로 다른 기능을 하고 사람들마다 포함되어있는 워크스페이스가 다르고? 약간 이런 부분때문이 아닐까 라는 생각이다. withCredentials: true는 지난 포스팅에서 다뤘으므로 넘어간다.

 

성공했을 경우(then) 워크스페이스는 생성되고, 모달을 끄고, 모달 내부의 각 input값을 초기화한다.

실패했을 경우 에러로그를 direction에 기반하여 콘솔에 띄운다. useCallback Hook을 썼으므로, 넘겨지는 데이터인 newWorkspace와 newUrl을 마지막에 삽입한다.

 

setShowCreateWorkspaceModal은, 그냥 쉽게 생각하면 true일 경우 위 움짤의 모달을 띄우고, false면 사라지게 하는 것이다. onCloseModal은 이름부터 모달을 닫는 것이며, onClickCreateWorkspace는 이름부터 워크스페이스를 새로 만드는 것임을 알 수 있으므로, 이부분은 어렵지 않을 것이다.

 

div

여기서 Modal 태그가 보이는데, 이는 Modal 컴포넌트를 불러오는 것이다. 5행에서 확인할 수 있다. 위에서 잠깐 언급한 show가 등장을 하는데, show는 그냥 보이는지의 여부를 나타낸다고 생각하면 된다. Modal 컴포넌트에서 show와 onCloseModal을 인터페이스로 타이핑했던 것을 생각해보면, 이게 뜬금없이 등장한 것은 아님을 알 수 있을 것이다. showCreateWorkspaceModal이 모달을 띄우는 역할을 한다는 것을 생각해보면 이해가 될 것이다. 반대로 모달을 끄는 것은 onCloseModal일 것이고.. onCreateWorkspace는 위에서 설명했으므로 넘어간다.

 

Label과 Input, Button 태그는, styled-components를 사용한 것으로만 생각해도 되고, 주목해서 봐야 할 부분은 newWorkspace, onChangeWorkspace, newUrl, onChangeNewUrl이다. 사실 주목해서 볼 필요가 없긴 하다. useInput Hook을 사용한 것에 불과하기 때문이다. 상술하기도 했지만, 그냥 이것들은 여기에 쓴 값을 그대로 e.target.value로 설정하는 것이다.

 

 

흐름 정리

다시 보자. 사실 저 왼쪽의 메뉴들은 생략했지만.. 어차피 스타일 입힌 거에 불과하다

  1. AddButton을 누름으로써 onClickCreateWorkspace 함수가 실행이 되고, 그에 따라 Modal(버튼, 인풋 등의 스타일링이 입혀진 컴포넌트)이 소환된다. (여기서, e.stopPropagation()에 따라 div의 바깥 부분을 누를 경우 모달이 꺼지게 된다.)
  2. 두 가지 input(워크스페이스 이름, 워크스페이스 URL)에 값을 입력할 경우 전부 useInput Custom Hook에 따라 그 값 그대로 value 처리가 된다.
  3. 마지막으로, 생성하기를 눌렀을 때 axios.post로 서버와 API통신을 하며 Workspace가 생성된다.
profile

Today Sangmin Learned

@steadily-worked

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!