2024년 4월 첫째주
1. userAgent
- 사용자가 접속중인 브라우저 , OS, 버전 등의 정보를 담고 있다.
- 브라우저는 서버에 보내는 모든 요청에 userAgent 문자열이라고 부르는 자신의 정체성을 알리는 헤더를 싣어 보낸다.
- 이 문자열은 보통 브라우저 종류, 버전 번호, 호스트 운영체제를 포함한다.
- 클라이언트에서는 Javascript 의
NavigatorId.userAgent
속성을 통해서 userAgent 문자열에 접근 가능하다.
언제 사용할까?
- 웹 브라우저의 종류가 많고, 각각의 엔진을 사용하던 시절에는 각 브라우저별로 동일한 서비스를 제공하기 위해서 사용되었다.
- 하지만 현재 대부분의 브라우저들이 크롬/블링크 엔진을 사용하고 있기때문에 현재는 브라우저에 대한 정보보다는 접속한 컴퓨터 OS, 모바일 디바이스를 구분하는 역할로서 많이 쓰인다.
- 예를들어, 사내 서비스에서는 두가지 목적으로 사용한 경험이 있다.
- 사용자 접속 환경(모바일/데스크톱)에 대한 로그를 남기기 위해.
- 모바일 디바이스에서 접속 중인지 여부를 확인하기 위해
ref - https://developer.mozilla.org/en-US/docs/Web/API/Navigator/userAgent
2. package.json - 의존성 버전 고정하기
사내 프로젝트에서 사용중인 msw 는 0.7.4 버전이다. 그러다보니 어느날 새로운 패키지가 추가되고 나서 아래와 같은 에러가 나면서 msw 모킹함수가 실행이 되지 않았다.😖
Type Error: response2.headers.all is not a function
조금 찾아보니, msw 하위 의존성인 headers-polyfill 패키지가 3.3.0 버전으로 업그레이드 되어서 난 에러이고, headers-polyfill 패키지는 3.3.0 버전부터 all
메서드들 삭제했다고 한다.😑
https://github.com/mswjs/headers-polyfill/releases/tag/v3.3.0
그래서나는 에러였고, 이를 해결하기 위해서는 하위 의존성인 headers-polyfill 패키지의 버전을 3.3.0 보다 아래로 고정시켜야했다. 이 때 yarn 패키지 매니저에서는, package.json 의 resolution 이라는 필드를 사용하여 의존성 버전을 고정시킬 수 있다. ref - https://classic.yarnpkg.com/lang/en/docs/selective-version-resolutions/
즉, package.json 의 의존성들의 특정 버전이나 범위를 고정할 수 있다. 위에서 겪었던 문제처럼, 하위 의존성 패키지에 업데이트가 있었는데, 이를 의존하는 패키지가 새로운 버전에 대응되지 않을 때 하위 의존성 패키지의 버전을 고정시키기 위해 사용 가능하다.
찾아보니 요거는 yarn 패키지매니저에서 사용가능한거고, npm이나 pnpm에서는 overrides라는 이름으로 동일한 기능을 지원하고 있다.
3. React- useState의 값은 어디에 저장될까?
useState 내부 코드
function useState(initialState) {
var dispatcher = resolveDispatcher();
return dispatcher.useState(initialState);
}
- useState 뿐만 아니라, 모든 훅의 내부 코드는 위의 형태를 가진다.
- dispatcher 에는 resolveDispatcher 함수의 결과가 할당 되고, dispatcher의 useState 메서드에 초기값을 전달하고, 반환 된 값을 리턴하고 있다.
function resolveDispatcher() {
var dispatcher = ReactCurrentDispatcher.current;
return dispatcher;
}
- resolveDispatcher 는 ReactCurrentDispatcher 라는 객체의 current 프로퍼티를 반환하고 있는데, 여기서 ReactCurrnetDispatcher 는 전역에 설정되어 있는 객체이다.
- 따라서, useState가 반환한 상태의 배열은 전역 객체로부터 오고,
- 훅을 호출하면 클로저 동작으로 컴포넌트 밖에 있는 외부 스코프에 존재하는 상태에 접근을 하게 된다.
- 따라서, 컴포넌트 내부에서 값을 변경하면 외부의 값이 변경된다.
- 따라서 함수 컴포넌트의 바디 전체가 리렌더링이 되어도, 외부 스코프에 있는 값은 유지 된다.
위와 같이 클로저를 사용하여 동작하는 setState를 짤막한 코드로 표현하자면 아래와 같다.
let _value;
export useState(initialValue){
if (_value === 'undefined') {
_value = initialValue;
}
const setValue = newValue => {
_value = newValue;
}
return [_value, setValue];
}
요거는 추후에 더 공부하고 정리하겠다😶
4. useEffect 의 cleanup 실행 시점
- useEffect 의 cleanup 은 컴포넌트가 unmount 될 때 실행되는게 아니라, 리렌더링 될 때 실행된다.
- props이 변경 되었을 때의 경우를 대비하여 리렌더링, 즉 컴포넌트가 업데이트 될 때 마다 실행시켜준다.
ref - https://ko.legacy.reactjs.org/docs/hooks-effect.html#explanation-why-effects-run-on-each-update
5. Trailing slash 란?
next.js 의 소스코드를 살펴보다가 trailing slash 판별 메서드가 있어서 찾아봤다 (꼬리 슬래시?!🤧)
- trailing slash 란 url 경로 뒤에 오는 슬래시를 지칭한다.
https://example.com/
- trailing slash 는 경로의 표준화와 일관성을 위해서 사용된다.
- 일부 웹 서버 및 프레임웍에서는 trailing slash 여부에 따라서 url을 다르게 처리하기도 한다.
trailing slash 가 없는 경우
- 서버는 해당 리소스를 우선적으로 파일로 간주하여 처리한다.
- 즉
https://example.com
이라고 표기 할 경우, 해당 이름의 파일이 있는지 확인한다. - 없을 경우 해당 이름의 디렉토리를 확인하고, 디렉토리가 있으면 그 안의 기본파일 (index.html) 을 확인 후 서빙한다.
trailing slash 가 있는 경우
- 서버는 해당 리소스를 우선적으로 디렉토리로 간주한다.
- 해당 이름의 디렉토리를 확인하고, 디렉토리가 있으면 그 안의 기본파일 (index.html)을 확인한다.
즉, trailing slash 를 명시해줄 경우 파일 확인 동작을 생략 가능하여 응답 속도가 살짝 빨라질 수 있다.
6. 멱등성(Idempotent)
- 멱등하다는 것은, 첫번째 수행을 한 뒤 여러차례 적용해도 결과가 변경되지 않는 작업
- 즉 멱등한 작업은 한 번 수행해도, 여러번 수행해도 결과가 같아야 한다.
멱등한 HTTP 요청
- GET,PUT,DELETE 처럼 리소스를 조회하거나 대체하는 메서드는
멱등
하다.- PUT은 여러번 호출 해도, 매번 같은 리소스로 업데이트 되고, DELETE는 열버ㅓㄴ 호출 해도 삭제된 리소스에 대한 결과는 달라지지 않는다.
- 반면 서버 데이터를 변경하는 POST,PATCH는 호출 할 때 마다 응답이 달라지기 때문에 멱등한 요청이 아니다.
멱등성 보장하기
- 멱등키를 API 요청에 포함하기
- 이전 요청과 동일한 멱등키를 가진 요청을 받으면, 서버에서 해당 요청을 중복으로 판단하여 실제로 처리하지 않고, 첫 요청과 같은 응답만 반환하는 방식
- 요청 본문, URL 쿼리 매개변수, 헤더 중 하나에 멱등키를 보내면 됨 (but IETF 에서는 요청 헤더에 포함시키는 방법 권장.)
Idempotency-Key: {IDEMPOTENCY_KEY}
- 이 때, 클라이언트에서 보내는 멱등키는 uuid 와 같이 무작위적인 고유한 값이어야 한다.
ref - https://www.tosspayments.com/blog/articles/dev-1?from=category