반응형

이번 글에서는 구글 태그 관리자 데이터 레이어 (dataLayer)에 대해 알아보겠습니다.

구글 태그 관리자를 제대로 활용하려면 데이터 레이어를 사용해야 합니다.

사실 조금 어려운 개념입니다. 저도 처음 접했을 때 이해가 잘 되지 않았습니다.

여러분도 처음 들어본 개념이라면 이해가 되지 않으실겁니다. 그래도 끝까지 읽어주세요.

데이터 레이어 = 태그 관리자로 정보를 전달하기 위한 자바스크립트 개체

데이터 레이어는 웹사이트에서 태그 관리자로 정보를 전달하기 위한 자바스크립트 개체입니다.

(자바스크립트란 개발 언어 중 하나이며, 자바 언어와는 별개의 언어입니다 ^^;)

페이지 정보나(페이지 제목, URL) 회원의 구매 정보(결제수단, 상품카테고리) 등을 넣을 수 있습니다.

그리고 그 값을 GTM으로 수집해서 GA에서 분석 용도로 활용할 수 있습니다.

출처 ☞ https://www.analyticsmania.com/post/datalayer-push/#gref

데이터 레이어는 생산성을 200% 높여줍니다.

데이터 레이어는 왜 사용해야 할까요? 데이터 레이어는 구글 도움말 문서를 봐도 사용을 권장하고 있습니다.

좀 더 유연하고 쉽게 GA 구축을 가능하게 해주며 불필요한 개발 리소스가 낭비되지 않게 해줍니다.

아래 자바스크립트가 데이터 레이어 소스 코드 예시입니다. dataLayer.push 영역 다음 부분이 배열입니다.

소스를 살펴보니 userId, weather 등의 정보를 담고 있습니다. GA가 자동으로 수집하지 않는 정보입니다.

때문에 별도로 수집할 필요가 있습니다. dataLayer가 그 역할을 도와준다고 보시면 됩니다.

출처 ☞ 시모 아하바 블로그 (https://www.simoahava.com/analytics/data-layer/)

가급적 개발 소스 상에 삽입하는 방향으로 적용하는 것으로 권장!

데이터 레이어는 GTM에서 맞춤 HTML 기능을 사용해서 삽입할 수 있지만

가급적 개발 소스 상에 데이터 레이어 스크립트를 삽입하는 것을 권장드립니다.

이유는 웹페이지가 리뉴얼이 되거나 일부 영역의 UI가 바뀌게 되면

맞춤 HTML을 활용해서 삽입한 경우 기존 값을 수집하지 못할 수 있기 때문입니다.

앞에서 말씀드린 내용이 이해가 되시나요? 데이터레이어를 한번에 이해하는 것을 어렵습니다.

태그 관리자를 사용하면서 벽에 부딪히는 경우가 바로 데이터레이어 라고 해도 무방합니다.

하지만 데이터레이어를 이해하면 화면 상에 없는 값도 수집할 수 있기 때문에 굉장히 유용합니다.

 

출처: https://entrench-consulting.com/ko/data-tag-management/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A0%88%EC%9D%B4%EC%96%B4datalayer%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C%EC%9A%94/#page-content

반응형
반응형

meta viewport(메타 뷰포트 태그) 사용법

 

 

얼마 전에 meta 태그 사용법이란 글을 썼는데 

 

[html] meta 태그 사용법

 

위 글에서 다루지 못한(빠진) 것들을 다루어 보려고 해요.

 

힌트를 주신 admin 님께 감사합니다.^^

 

오늘 다룰 부분은 meta viewport(메타 뷰포트 태그) 입니다.

 

웹페이지 소스를 보면 간혹 head 에 이런 meta 구문을 보신 적이 있으실 거예요.

 

<meta name="viewport" content="width=device-width">

 

 

meta viewport 태그는 애플이 아이폰, 아이패드 등 자사의 모바일 브라우저의

 

뷰포트(viewport) 크기 조절을 위해 만들었습니다. (뷰포트에 대한 설명은 본문 참조)

 

meta viewport 태그는 W3C 명세에는 없지만,(따라서 표준이 아님)

 

iOS 장치(아이폰 운영체제 브라우저 safari)가 널리 사용됨에 따라 사실상 표준처럼

 

사용되고 있고, 다른 브라우저들(Opera, Android,  Mobile firefox(Fennec) 등)도 이 태그를 채택하게 됩니다.

 

 

그런데, IE10(snap mode) 은 뷰포트 크기 조절을 위해 meta viewport 태그 대신에  표준으로 제안된

 

@viewport rule을 사용합니다.

 

@viewport는 W3C에 제안된 표준이고, Opera Mobile 11에서도 지원합니다.

 

그럼에도 여전히 viewport meta 설정을 고수하는 브라우저들이 있습니다.

 

따라서 아이폰과 IE10 브라우저 양쪽을 타켓으로 웹페이지를 설계하려면  현재는 두 가지 방식으로

 

viewport 크기 조절 하는 것이 필요합니다.   

 

 

 예

<head>
<meta name='viewport' content='width=device-width' /> 
<style type='text/css'>
@-ms-viewport { width: device-width; }
@-o-viewport { width: device-width; }
@viewport { width: device-width; }
</style>
</head>

 

 

이 페이지에서는 viewport란 무엇인고, 왜 필요한지 알아보고,  meta viewport 태그 사용법을 다루겠습니다.

 

css @viewport rule은 다음 시간에 다루어 볼게요

 

 

viewort란?

 

viewport란 우리말로 보임창, 즉 화면 상의 화상 표시 영역을 뜻합니다.

 

데스크탑(pc)의 뷰포트와 모바일 뷰포트는 약간 다릅니다.

 

 

- 데스크탑(pc)의 뷰포트는 웹브라우저 창(visible area)의 뷰포트와 같음.

 

   사용자가 브라우저 창의 크기를 조절하면서 뷰포트 크기를 조절할 수 있음.

 

   웹페이지가 뷰포트보다 작으면, 스크롤로 나머지를 볼 수 있음.

 

이미지 출처: 애플

 

- 모바일 뷰포트는 웹브라우저 창(visible area)보다 크거나 작을 수 있음.


   그리고 창, 스크롤바, 크기조절 버튼이 없음. 


   대신, 상하좌우로 움직이거나, 더블탭이나, 확대 축소(zoom in/out)를 통해 뷰포트 배율을 바꿀 수 있음.(크기가 아니라)

  

 

뷰포트 980px

 

 

이미지 출처: 애플

 

 

viewport 크기 조절이 필요한 이유?

 

 

데스크탑에 기반하여 설계된 웹페이지를 모바일에서 보면 기본 뷰포트가 980px이기 때문에

 

내용이 작게 보입니다. (위 이미지'뷰포트 980' 참조)

 

뷰포트 설정을 하게되면 다양한 모바일 기기에서도 페이지의 너비나 화면 배율을 설정할 수 있습니다.

 

모바일 장치에 최적화된 웹페이지를 만들려면 html 문서 head에 뷰포트 설정을 포함해야 합니다.  

 

 

뷰포트 너비 320로 설정한 화면

 

 

 

 

meta viewport 태그 사용법 (간단 설명)

 

간단 설명과 긴 설명으로 구분했어요. 필요하신 부분을 골라서 보세요

 

1. viewport 너비 설정

 

<meta name="viewport" content="width=500">

 

너비는 px 단위이며 meta 태그에서는 단위 생략함 

 

content에 여러 속성값을 쓸 경우 쉼표로 분리함.

 

 

 

2. 너비를 장치너비로 설정(추천)

 

<meta name="viewport" content="width=device-width">

 

브라우저 너비를 장치 너비에 맞추어 표시함.

 

 

3. 너비를 장치높이로 설정

 

<meta name="viewport" content="height=device-height">

 

 

4. 초기 화면 배율(initial-scale) 설정(zoom 레벨 설정)

 

<meta name="viewport" content="width=device-width, initial-scale=1.0">

 

1.0은 100%와 같음. initial-scale은 긴 설명 참조


 

5. 최소 최대 화면 배율 설정(minimum and maximum scale)


<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">


최소 설정은 사용자가 너무 극닥적으로 화면 축소하는 것을 방지함 

 

(위 예에서는 초기값과 최소 화면 배율 설정을 같이 함)

 
 

<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=3.0">

 

최대 화면 배율 설정은 극단적으로 화면 확대하는 것을 방지함.

 

(위 예는 최소와 최대 배율을 같이 사용한 예)

 

(minimum-scale, maximum-scale값은 긴 설명 참조)

 

 

6. 사용자가 크기 조절하기를 원치 않을 때


<meta name = "viewport" content = "user-scalable=no, width=device-width">

 

 

 

meta viewport 태그 사용법 (긴 설명)

 

(Safari Developer Library 사이트를 번역 정리한 것입니다)

 

1. viewport

 

iOS(아이폰 운영체제)에서 페이지를 표시할 때 사용하며,  창 크기를 바꿈

 

▷구문


<meta name = "viewport" content = "width = 320, initial-scale = 2.3, user-scalable = no">

 

▷설명

 

보통 viewport meta 태그는, 뷰포트의 너비와 초기 배율(zoom 레벨)을 설정하기 위해 사용.

 

예> 웹 페이지가 980px보다 폭이 좁으면, 뷰포트의 너비를 내용에 알맞도록 설정해야 함.


iOS에 기반한 웹을 디자인하려면, width를 device width로 설정해야 함.

 

하기 표 1은, viewport meta key와 그들의 기본값에 의해 지원되는 속성을 서술함. 


여러 개의 속성을 쓰려면  쉼표로 구분된 목록을 사용 함.

 

여러 개의 속성을 설정할 때 다음 규칙을 따른다.


-  세미콜론(;)을 구분 문자로 사용하지 말 것
- 공백은 구분 문자로 작동할 수 있지만, 쉼표를 추천함.
- 숫자 속성으로, 값이 숫자가 아닌 문자를 포함하지만 숫자로 시작되면, 숫자 접두어는 속성값으로 사용된다.

 

예> 1.0x는 1.0과 같음. 123x456은 123과 같음. 매개변수가 숫자로 시작하지 않으면 값은 0임.

 

장치의 치수(dimension)을 참조할 때, 숫자 값 대신  2에 사용된 항수를 사용해야 함
 
예> width 320 대신 device-width, height 480 대신 device-height 사용(세로 화면에서)

 

모든 viewport 속성을 일일이 설정할 필요 없음.


일부 값이 설정되기 만하면 iOS 사파리는 다른 값을 추론한다.


예> scale 1.0으로 설정하면 사파리는 뷰포트 너비를  세로화면에서 device-width로 가정하고,


가로 화면에서 device-height 로 가정함.


width 980px과 initial scale 1.0으로 원하면, 둘을 모두 설정해야 한다.


예> width를 device-width로 설정하기


<meta name = "viewport" content = "width = device-width">

 

초기 화면 배율 1.0으로 설정하기


<meta name = "viewport" content = "initial-scale = 1.0">

 

초기 화면 배율 설정하고 크기 조절을 사용하지 않게 하기 


<meta name = "viewport" content = "initial-scale = 2.3, user-scalable = no">

 

표 1

속성값 설명
width 뷰포트의 너비(px).
기본값 : 980
범위 : 200~10,000 px
속성값은 표2처럼 항수(예:device-width)
로 설정할 수도 있음.
----------------------------------
height 뷰포트의 높이(px)
기본값 : width 속성값과 장치 영상의 가로 세로 비에  기초하여 계산됨.
범위 : 223~10,000 px
속성값은 표2처럼 항수로 설정할 수도 있음.
----------------------------------
initial-scale 뷰포트의 초기 배율(곱하는 수)
기본값 : 보이는 영역에서 웹페이지에 맞추기 위해 계산됨
범위 : minimum-scale과 maximum-scale 속성값으로 결정됨
----------------------------------
minimum-scale 뷰포트의 최소 배율값
기본값 : 0.25
범위 : 0~ 10.0
----------------------------------
maximum-scale 뷰포트의 최대 배율값
기본값 : 5.0
범위 :  0~ 10.0
----------------------------------
user-scalable 사용자가 화면을 축소/확대(zoom in/out))
할 수 있는지 여부를 결정
(사용자가 뷰포트의 배율을 변경할 수 있든 아니든)
yes는 크기 조절을 가능하게 설정(기본값)
no는 크기 조절이 불가능하게 설정
no로 설정하면 웹페이지가 input 영역에서 텍스트를 입력할 때 스크롤되는 것도 방지한다.

 

표 2

속성값 설명
device-width 장치 너비(px)
device-height 장치 높이(px)

*meta 태그에서 px은 생략함
 

2. apple-mobile-web-app-capable


웹응용프로그램을 전체 화면에서 작동시킬지를 설정 

 

▷구문

 

<meta name="apple-mobile-web-app-capable" content="yes">

 

▷설명


content가 yes면, 전체화면 모드로 작동함. no면 작동하지 않음.


기본값은 Safari가 웹 내용을 표시하도록 사용하는 것.

 

웹페이지가 window.navigator.standalone (읽기 전용 Boolean 자바스크립트 속성)을 사용하여

전체 화면 모드로 표시할지 결정할 수 있음.

 

3. apple-mobile-web-app-status-bar-style

 

웹 응용프로그램을 위한 상태 막대의 스타일 설정

 

▷구문


<meta name="apple-mobile-web-app-status-bar-style" content="black">

 

▷설명


apple-mobile-web-app-capable에 서술한 것처럼 전체화면 모드를 먼저


지정하지 않으면 효과가 없음.

 

content가 default이면, 상태 막대는 보통으로 나타남.(기본값)


black으로 설정하면, 상태 막대는 검은색 배경임.


black-translucent 이면 상태바 막대는 검정과 반투명


*default 또는 black으로 설정하면  웹 내용은 상태 막대 아래 표시됨.

 

*black-translucent로 설정하면, 웹 내용이 전체 화면에 표시됨,

 일부는 상태 막대로 인해  흐릿해짐.


4.  format-detection


iOS safari 웹페이지에서 가능한 전화번호의 자동 탐색이 가능하거나 불가능하게 설정


▷구문


<meta name="format-detection" content="telephone=no">

 

▷설명


기본적으로 iOS safari는 전화번호처럼 형식화된 어느 문자열이든 감지하여


전화로 호출하는 링크를 만듦.


telephone=no 라고 지정하면 이 특정을 불가능하게 함.

 

 

 

 

<같이 참조하면 좋은 글>

 

http://www.quirksmode.org/mobile/metaviewport/  에서 ideal viewport 를 보면, 모바일 브라우저별

 

이상적인 뷰포트가 나옵니다.

 

 https://developer.apple.com/library/safari/documentation/AppleApplications/Reference/SafariHTMLRef/Articles/MetaTags.html#//apple_ref/doc/uid/TP40008193-SW8

 

 http://benfrain.com/understanding-the-viewport-meta-tag-and-css-viewport/

 

[css] 미디어 쿼리, @media query 이해하기

 

출처: https://aboooks.tistory.com/352

반응형
반응형

안녕하세요. 
오늘은 React의 custom hooks에 대해 알아보고 직접 만들어보는 시간을 가져보도록 하겠습니다.

Custom hook이란?

요즘 React 개발 트랜드는 react hook을 적극 활용하는 것입니다. hook을 사용함으로 인해 class component 없이도 여러 state 값을 변경해줄 수 있게 되었고, 이는 React 개발자들이 function component를 통한 간결한 코드 작업을 할수있게끔 만들어주었습니다.
useState, useEffect 등등 hook을 사용하는 것만으로도 코드가 훨씬 보기 좋아졌지만, 반복되는 훅 활용 메소드들을 하나로 줄여줌으로써 더 간결하고 보기 좋은 코드를 만들 수 있는 것이 바로 custom hooks입니다. 이름에서 알 수 있다시피 custom hook은 개발자 본인이 직접 hook을 만드는 것이죠.

그렇지만 중요한 포인트가 있습니다. custom hook의 이름은 무조건!!!! use로 시작해야합니다. 이 점은 꼭 유념해주셔야 합니다.

사용 예제 코드

custom hooks 적용 전

Jsonplaceholder API를 사용하여 간단하게 구현해보도록 하겠습니다.
우선 UserList, UserDetail 컴포넌트를 생성했습니다. Jsonplaceholder에서 유저정보 10개를 받아 리스트로 보여주고 유저이름을 클릭하면 UserDetail page로 이동하는 아주 간단한 예제입니다.

//UserList.js

import React, { useEffect, useState } from "react"
import { Link } from "react-router-dom"

function UserList() {
  const [userList, setUserList] = useState([])
  const url = "https://jsonplaceholder.typicode.com/users"

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(resJson => setUserList(resJson))
  }, [])

  return userList.map(user => (
    <Link
      to={`/${user.id}`}
      key={user.id}
      className="list-group-item list-group-item-action"
    >
      <div>{user.name}</div>
    </Link>
  ))
}

export default UserList
//userDetail

import React, { useEffect, useState } from "react"
import { useParams } from "react-router-dom"

function UserDetail(props) {
  const [userInfo, setUserInfo] = useState([])
  const { id } = useParams()
  const url = `https://jsonplaceholder.typicode.com/users/${id}`

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(resJson => setUserInfo(resJson))
  }, [])

  return (
    <div>
      {userInfo.name}
      <br />
      {userInfo.email}
      <br />
      {userInfo.phone}
    </div>
  )
}

export default UserDetail

hook을 이용하여 쉽게 구현하였지만 아쉬움이 남습니다. 두 컴포넌트에서 data를 받아오는 useEffect 내의 fetch함수 부분이 똑같기 때문에 이를 하나로 통일시키고 싶습니다. 그럴때 우리는 custom hooks를 통해 이를 해결할 수 있습니다.

custom hook 적용해보기

두 컴포넌트의 fetch함수를 useFetch라는 hook을 만들어서 통일시켜주도록 하겠습니다.
우선 hooks라는 디렉토리를 만든 후 useFetch.js를 만들어줍니다.

hooks 디렉토리를 꼭 만들어야하나요?

꼭 그래야 하는 것은 아니지만 나중에 custom hooks가 많아진다면 디렉토리 구조가 복잡해지겠죠?? 그럴때를 대비해서 hooks 디렉토리를 만들어 놓는 것이 보기 좋고 그때그때 꺼내서 사용하기도 편리합니다.

그럼 useFetch.js 내 코드를 작성해보도록 하겠습니다.

//useFetch.js

import { useEffect, useState } from "react"

function useFetch(url) {
  const [data, setData] = useState([])

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(resJson => setData(resJson))
  }, [url])

  return data
}

export default useFetch

UserList,UserDetail 컴포넌트에서 겹쳤던 fetch부분을 그대로 넣어주고 data를 return 해주면 끝입니다. url을 인자로 받고 해당 url을 useEffect의 의존성 배열로 넣어주면 custom hook이 원할때 잘 호출되겠죠?? 이제 UserList, UserDetail 컴포넌트가 어떻게 변경할 수 있는지 살펴볼까요??

custom hooks 적용 후

//UserList.js

import React from "react"
import { Link } from "react-router-dom"
import useFetch from "./hooks/useFetch"

function UserList() {
  const userList = useFetch("https://jsonplaceholder.typicode.com/users") 

  return userList.map(user => (
    <Link
      to={`/${user.id}`}
      key={user.id}
      className="list-group-item list-group-item-action"
    >
      <div>{user.name}</div>
    </Link>
  ))
}

export default UserList
//UserDetail.js

import React from "react"
import { useParams } from "react-router-dom"
import useFetch from "./hooks/useFetch"

function UserDetail(props) {
  const { id } = useParams()
  const userInfo = useFetch(`https://jsonplaceholder.typicode.com/users/${id}`)

  return (
    <div>
      {userInfo.name}
      <br />
      {userInfo.email}
      <br />
      {userInfo.phone}
    </div>
  )
}

export default UserDetail

어떤가요?? 단 한줄로 useEffect와 useState 그리고 fetch 함수를 대체할 수가 있어졌습니다. 이전 코드보다 훨씬 간단해졌고 custom hooks의 네이밍이 잘되어있다는 가정하에 코드 가독성도 훨씬 높아지지 않았나요?? 지금은 fetch함수를 사용하는 component가 2개밖에 없지만 fetch함수를 사용하는 컴포넌트가 더 많으면 많을 수록 우리의 custom hooks는 그 힘을 발휘할 것입니다 ㅎㅅㅎ

마무리

이렇게 컴포넌트 로직을 뽑아내서 정의한 후 간편하게 호출할 수 있다는 것이 custom hooks의 정말 큰 장점이 아닐까 생각이됩니다.
이 밖에도 여러개의 input들이 존재하고 각각 여러개의 state 값을 control할 때에도 useInput이라는 custom hooks를 사용하여 코드를 간단하게 만들 수 있을겁니다. 아니면 user 정보를 useAuth라는 custom hooks를 만들어 그때그때 편하게 호출할 수도 있겠죠?
custom hooks를 좋은 네이밍과 더불어 사용하면 코드의 가독성을 높이고 짧고 간결한 코드를 작성할 수가 있을겁니다.

 

출처: https://velog.io/@kysung95/%EC%A7%A4%EB%A7%89%EA%B8%80-Custom-Hooks%EC%9D%84-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EC%9E%90

반응형

'Web > Js' 카테고리의 다른 글

Nuxt js dot env 적용하기 (자체 cross-env 적용기)  (0) 2022.05.12
데이터레이어(dataLayer)란 무엇일까?  (0) 2022.03.18
useCallback 과 useMemo 의 차이  (0) 2022.03.16
componentDidUpdate  (0) 2022.03.04
package-lock.json이란?  (0) 2022.02.24
반응형

 


먼저 메모이제이션(memoization) 이란?

 

useMemo 함수에 대해서 알아보기 전에 알고리즘 시간에 자주 나오는 메모이제이션(memoization) 개념에 대해서 잠깐 짚는다.

memoization이란 기존에 수행한 연산의 결과값을 어딘가에 저장해두고 동일한 입력이 들어오면 재활용하는 프로그래밍 기법을 말한다. 

memoization을 절적히 적용하면 중복 연산을 피할 수 있기 때문에 메모리를 조금 더 쓰더라도 애플리케이션의 성능을 최적화할 수 있다.

 

useMemo와 useCallback 을 너무나도 어렵게 설명하는 곳이 많아서 여기서는 간단하게만 적어본다.

 


1. useMemo

 

메모이제이션된 ''을 반환한다.


  • 용법
useMemo(() => fn, deps)

 

⭐️ useMemo 는 deps 가 변한다면, () => fn 이라는 함수를 실행하고 그 값을 반환한다. ⭐️

deps 는 dependency이며, useMemo가 이 deps라는 것에 '의존'한다는 뜻이다.

 

  • 예시
import React, { useState, useCallback, useMemo } from "react";

export default function App() {
  const [ex, setEx] = useState(0);
  const [why, setWhy] = useState(0);

  // useMemo 사용하기
  useMemo(() => {console.log(ex)}, [ex]);

  // 두 개의 버튼을 설정했다. X버튼만이 ex를 변화시킨다.
  return (
    <>
      <button onClick={() => setEx((curr) => (curr + 1))}>X</button>
      <button onClick={() => setWhy((curr2) => (curr2 + 1))}>Y</button>
    </>
  );
}

 

 

이런 작고 소중한 버튼이 있다.

먼저 위 코드는 X라는 버튼을 누를 때에 'ex' 라는 상태값이 변화하는 코드이다.

 

useMemo(() => {console.log(ex)}, [ex]) 

 

에서 deps 는 [ex] 이다.

ex 가 변할 때에만 () => {console.log(ex)} 이 실행된다.

 

따라서 X 버튼을 누를 때에만 콘솔창에 ex 값이 출력된다.

Y 버튼을 누르더라도 APP 이라는 함수 컴포넌트가 전부 재실행 되지만,

ex 라는 값은 변하지 않았기 때문에 useMemo는 에는 아무런 변화가 없다.

 


2. useCallback

 

메모이제이션된 '함수'를 반환한다.

 

 

이 친구가 useMemo 보다 어렵다. useMemo 는 그냥 함수를 실행해버리는데, 얘는 함수를 반환한다.

 

useCallback(fn, deps)

 

useCallback  deps 가 변한다면, fn 이라는 새로운!함수를 반환한다.

 

import React, { useState, useCallback, useMemo } from "react";

export default function App() {
  const [ex, setEx] = useState(0);
  const [why, setWhy] = useState(0);

  // useCallback 이 () => {console.log(why)} 라는 함수를 반환한다.
  const useCallbackReturn = useCallback(() => {console.log(why)}, [ex]);

  // useCallback 이 담겨있는 함수를 실행
  useCallbackReturn()

  return (
    <>
      <button onClick={() => setEx((curr) => (curr + 1))}>X</button>
      <button onClick={() => setWhy((curr2) => (curr2 + 1))}>Y</button>
    </>
  );
}

 

아까 그 코드와 같은 버튼을 보여주는 코드이다.

위의 useCallback  () => {console.log(why)} 라는 함수를 반환해주고 있다.

 

위의 useCallback 은 다음의 순서로 진행될 것이다.

 

  1. 처음 컴포넌트가 시작될 때 실행 () => {console.log(0)}
  2. ex 가 변할 때까지 함수는 () => {console.log(0)}
  3. ex 가 변한다면 그제서야 why 의 값을 가져와서 () => {console.log(새로운 값)}

 

예를 들어서 Y 버튼을 다섯번 누른다고 해보자.

Y 버튼이 눌리면 'why'라는 상태의 값이 1씩 증가할 것이다.

 

 

위의 움짤에서 보듯이, Y를 다섯번 누를 때 동안에는 계속 함수가 () => {console.log(0)} 이다.

(물론 이 때 why라는 상태값은 계속 값이 증가한다.)

그러다가 X 버튼을 누르면서 ex 라는 변수(deps) 가 변하자 마자, () => {console.log(5)} 를 반환한다.

deps가 변해야 함수 컴포넌트와 상태값(why) 를 공유하는 것이다!!

 

따라서 useCallback 은 함수와는 상관 없는 상태값이 변할 때,

함수 컴포넌트에서 불필요하게 함수를 업데이트 하는 것을 방지해준다.

 

다만, deps 를 잘못 설정하면 아무리 함수 컴포넌트를 재실행해도 함수가 변하지 않으면서

내가 원치 않는 상황이 올 수도 있으므로 섬세한 컨트롤이 필요하다..

 

이런 상황은 useMemo도 똑같다. useMemo 역시 Y 버튼을 5번 눌러도, X버튼을 안 누르면 실행이 되지 않는다.

 

추가로, react 공식 문서에서도 인정하듯이, 아래의 두 식은 같다.

 

useMemo((...)=>fn, deps) === useCallback(fn, deps)

 


3. useCallback 의 새로고침

 

useCallback 은 deps 가 변하면서 함수를 반환할 때, 형태가 같더라도 아예 새로운 함수를 반환한다.

 

const add1 = () => {};
const add2 = () => {};

 

위 두 함수는 같은가?

 

답은 두 함수는 전혀 같지 않다.

 

 

각 변수는 같은 함수를 바라볼 뿐 전혀 다른 변수이다.

바라보는 값만 같을 뿐, 전혀 다른 메모리를 가진 변수이다.

 


useCallback 은  새로운 함수를 반환한다

 

const useCallbackReturn = useCallback(() => {}, [ex])

 

여기서 ex 가 변할 때, useCallback 은 새로운 함수를 반환한다.

그 말은 즉, ex == 0 일 때와 ex == 1 일 떄의 () => {} 은 다른 함수다.

새로운 무기명 함수를 반환했기 때문이다. 이는 앞서 기술했듯이, 값이 같을 뿐 다른 메모리이다.

 

출처: https://basemenks.tistory.com/238

반응형

'Web > Js' 카테고리의 다른 글

데이터레이어(dataLayer)란 무엇일까?  (0) 2022.03.18
Custom Hooks을 만들어보자!  (0) 2022.03.17
componentDidUpdate  (0) 2022.03.04
package-lock.json이란?  (0) 2022.02.24
[Vue.JS] Vuex Store를 바인딩하는 4가지 방법  (0) 2022.02.22

+ Recent posts