TIL

241207 TIL

GoJay 2024. 12. 8. 03:27
  • 코드 리뷰 챌린지 서비스? 만들기
    • 코드 리뷰를 위한 체크리스트 부분을 작업했다.
    • 짧지만 현업에 계신 분들과 같이 작업해 보면서 배운 게 참 많았다.
      • 프로젝트를 할 때 어떤 순서로 준비하고 진행해나가는지, 처음으로 경험해 봤다.
      • 일단 현업에 있는 분들의 대화 자체를 따라가는 게 버겁다 보니 위축되는 게 좀 있다. 내 의견이 있다가도 뭔가 전달했을 때 잘 이해를 못 하면 '내가 뭘 잘못 얘기한 건가?' 싶다. 완전 6년 전 처음 사회생활 시작할 때의 모습이 떠올라서 속상했다.
      • 그래도 좋은 자극이 됐다. 개발 지식도 지식이지만, 현업에서 어떤 흐름으로 일 하는지, 주로 사용하는 도구는 무엇인지, 뭐가 일반적인 상식이고 뭐는 아닌지, 하나씩 잘 알아가야겠다.
    • 코드 리뷰 요청 시 만들 체크리스트 기능을 만들면서는 아래의 내용들이 허들이 됐다.
      • 드롭다운 메뉴를 만들고, 버튼을 누르면 메뉴가 펼쳐졌다가 메뉴 밖 아무 곳이나 눌러도 메뉴가 닫히도록 하고 싶었다. 해당 기능을 만드는 데 여러 시행착오와 어려움을 겪었다.
      • 먼저 onBlur 이벤트로 메뉴에 포커스 된 게 아웃되면 닫는 방식을 생각해서 구현이 가능한 건지 많이 찾아봤다. 그런데, 메뉴를 만들 때 사용한 ul - li 태그는 포커스가 안되기 때문에 onBlur 이벤트도 발생시키지 못한다는 문제가 있었다.
      • 찾아보니 HTML 요소에 tabIndex라는 속성을 주면 포커스가 안 되는 요소도 포커스가 되도록 설정할 수 있다는 걸 알게 됐다. tabIndex의 원래 용도는 접근성 등을 고려했을 때 키보드-마우스 이벤트로 특정 요소에 접근할 수 있도록 순서대로 포커스 시켜주는 것이다. 예를 들어 input이 여러 개 있는 회원가입 창에서 input에 커서를 두고 tab을 누르면 다음 input 위치로 자동으로 이동하는데, Form 요소가 아닌 태그에 tabIndex를 넣어주면 (쉽게 설명해서) 탭을 통해 접근할 수 있는 요소가 되도록 해준다.
      • 해당 속성을 이용해서, 먼저 ulli 요소에 tabIndex를 주고, 드롭다운 활성화 시 포커스를 가져가게 한 다음(useRef로 생성한 ref 변수로 focus()했다) onBlur 시 드롭다운 메뉴가 닫히도록 구현해 봤다.
      • 그런데, 이렇게 하니까 li로 만들어둔 드롭다운 메뉴를 클릭했을 때 해당 클릭 이벤트가 처리돼서 다음 이벤트 핸들러를 호출하고 동작을 처리하기도 전에 메뉴가 닫혀버려서 원하는 순서로 이벤트가 발생하지 않는 문제가 생겼다.
      • 비동기로 처리해 줘서 해결해보려 하다가, 배보다 배꼽이 더 커지는 것 같아 다른 방법을 찾았다.
      • useEffect로 컴포넌트가 처음 렌더링될 때 document 객체에 이벤트 리스너를 등록해서 드롭 다운을 펼치는 버튼을 제외한 모든 영역의 마우스 클릭 이벤트를 감지했다. 그리고, useEffect 클린업 함수로 컴포넌트 언마운트 시 이벤트 리스너를 떼는 식으로 구현했다.
      • 이렇게 하면 전역의 상태를 이벤트 리스너가 항상 감지해야 하기 때문에 비싼 비용이 발생하는 방식이라고 생각이 들었다. 하지만, 당장 구현해야 하는 기능이라 더 찾아보지 못하고 일단 만들어두긴 했다. 기회가 되면 같은 상황에서 문제를 해결할 수 있는 방법을 좀 더 찾아보던가 해야겠다.
  • 할 일 목록 관리 서비스 만들기
    • export default로 외부에 공개한 컴포넌트를 같은 폴더(또는 원하는 폴더 위치)의 index.ts에서 export { default as components } from './경로'로 정의해 주면, 외부에서 공개된 컴포넌트들을 받아와 사용할 때 경로를 간결하게 사용할 수 있다.
    • 예를 들어, components 밑에 있는 Button.tsx, Input.tsx, Menu.tsx, Toggle.tsx가 있을 때, 네 개 파일에서 각각 임포트해오려면 import 문만 네 줄이다. 그런데, components 폴더 하위에 있는 index.ts 파일에 외부 공개된 컴포넌트를 등록해 두면 4개의 컴포넌트들을 ./components라는 같은 경로에 가져올 수 있어서 편리하다.
    • 이번 프로젝트에선 API 요청을 axios로 해보려고 한다. axios는 비동기 통신 라이브러리다. Javascript나 브라우저 API가 기본 제공해 주는 도구가 아닌, 별도 설치(npm i axios)와 불러오기(import axios from 'axios')가 필요하다.
    • axiosfetch와 유사하게 정해진 인자를 전달 호출해 주면 Promise 객체가 값으로 반환된다.
    • fetch는 첫 번째 인자로 요청을 보낼 URL, 두 번째 인자로 method, header, body 등의 정보가 들어가는 옵션 객체가 전달된다.
    • axiosaxios.get 또는 axios.post 처럼 메서드 형태로 호출할 수 있다. HTTP method가 메서드 명에서 이미 특정되기 때문에 관련 정보는 다시 보내줄 필요가 없다.
    • axios는 첫 번째 인자로 URL 경로, 두 번째 인자로 fetchbody에 담던 요청 데이터를 넘긴다. 이때, axios는 기본적으로 직렬화를 지원하기 때문에 JSON.strigify를 사용할 필요가 없다.
    • axios는 인스턴스를 만들어서 기본 config 설정을 추가해 둘 수 있다. axios 인스턴스는 아래와 같이 만든다.
    // Axios 인스턴스 생성
    const instance = axios.create({
      baseURL: 'https://example.io/api/', // 기본 URL 미리 설정해두고, 이후에 실제 요청 보낼 땐 path 정보만 활용
      timeout: 5000, // 5000ms 경과 시점까지 서버의 응답이 없으면 에러 반환
      header: {
        "Content-Type": "application/json",
      }
    });
    • 만약에 인증/인가가 필요한 접근이고, 토큰 방식으로 인가가 이뤄지며, Access Token을 로컬에서 관리해야 한다고 했을 때, 토큰 정보를 API 요청이 이뤄지는 전역에서 접근 가능하면서, 동시에 어느 정도의 보안으로 감춰두는 노력이 필요할 수 있다. 이럴 때 instanceheader로 미리 토큰을 정의해 두고, 이후에 instance.get instance.post 처럼 요청을 사용하면 도움이 된다.
    • 아니면 axios.defualt.headers.commont['Authorization'] =Bearer ${accessToken}` 과 같은 방식으로 axios 라이브러리를 통해 전역 설정으로 Access Token을 관리할 수도 있다.
    • 하지만, axios.default.headers에 전역으로 등록할 수 있는 토큰 숫자는 한계가 있으며, 또한 프로젝트의 모든 곳에서 사용하는 axios 호출에 설정이 적용되기 때문에 의도치 않은 문제가 발생할 수 있다. 때문에, API 인가 토큰 키를 가지고 있는 axios 인스턴스를 별도로 만들어서 정보를 관리하는 것이 조금 더 안전하다.

'TIL' 카테고리의 다른 글

241209 TIL  (0) 2024.12.10
241208 TIL  (1) 2024.12.09
241206 TIL  (1) 2024.12.07
241205 TIL  (0) 2024.12.06
241204 TIL  (1) 2024.12.05