์žฌ๋ฐŒ๊ฒŒ ํ•ฉ์‹œ๋‹ค

๊ธฐ๋กํ•˜๊ธฐ, ๊ฐ€์‹œํ™”ํ•˜๊ธฐ

ํ”„๋กœ์ ํŠธ ๊ธฐ๋ก/BurnIN | React-Native ๋Ÿฌ๋‹ ์–ดํ”Œ

ReactNative๋กœ ๋Ÿฌ๋‹์–ดํ”Œ ๋งŒ๋“ค๊ธฐ | ์‹ค์‹œ๊ฐ„ ํƒ€์ด๋จธ ๊ตฌํ˜„

์€๋˜๋”” 2022. 8. 10. 23:55

2022.05.14 velog์— ์ž‘์„ฑํ–ˆ๋˜ ๊ธ€์ž…๋‹ˆ๋‹ค

 

๋Ÿฌ๋‹ ์–ดํ”Œ์ธ ๋งŒํผ ์ •๋ณด๊ฐ€ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ”๋€Œ์–ด์•ผ ํ•œ๋‹ค. ์‹ค์‹œ๊ฐ„์ด๋ผ๊ธฐ ๋ณด๋‹ค๋Š” ์ดˆ ๋‹จ์œ„๋กœ ๋ฐ”๋€Œ์–ด์•ผ ํ•œ๋‹ค๋Š” ๋ง์ด ๋” ์ ํ•ฉํ•˜๊ธด ํ•˜๊ฒ ๋‹ค. ์•„๋ฌดํŠผ ๋Œ€ํ‘œ์ ์ธ ์‹ค์‹œ๊ฐ„ ์ •๋ณด๋Š” '์‚ฌ์šฉ์ž๊ฐ€ ๋‹ฌ๋ฆฐ ์‹œ๊ฐ„'์ด๋‹ค. ์‹œ๊ฐ„์„ ๊ธฐ์ค€์œผ๋กœ ๊ณ„์‚ฐํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š” ๊ฐ’๋“ค์ด ์กด์žฌํ•˜๊ธฐ ๋•Œ๋ฌธ์—(ex ํŽ˜์ด์Šค, ์นผ๋กœ๋ฆฌ) ์ด ๊ฐ’์„ ์ž˜ ๊ด€๋ฆฌํ•ด์ค˜์•ผ ํ•œ๋‹ค ๐Ÿ˜Š ...

๊ตฌํ˜„ ๋ชฉํ‘œ โฐ

์•„๋ž˜ ์ด๋ฏธ์ง€์˜ ํƒ€์ด๋จธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ ์ž ํ–ˆ๋‹ค.

  1. 1์ดˆ์”ฉ ์ฆ๊ฐ€ํ•ด์•ผ ํ•˜๊ณ , ๋ฐ”๋€ ๊ฐ’์ด ํ™”๋ฉด์—๋„ ๋ฐ”๋กœ ๋ฐ˜์˜๋˜์–ด์•ผ ํ•œ๋‹ค.
  2. ์‚ฌ์šฉ์ž๊ฐ€ ์ผ์‹œ์ •์ง€ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ์‹œ๊ฐ„ ์ฆ๊ฐ€๋„ ๋ฉˆ์ถฐ์•ผ ํ•œ๋‹ค.
  3. ๋Ÿฌ๋‹์„ ์žฌ๊ฐœํ•˜๋ฉด ์ผ์‹œ์ •์ง€ ๋ฒ„ํŠผ ๋ˆ„๋ฅด๊ธฐ ์ „ ์‹œ๊ฐ„์—์„œ ๋‹ค์‹œ 1์ดˆ์”ฉ ์ฆ๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.

๊ธฐ๋ณธ ํƒ€์ด๋จธ ๊ตฌํ˜„

useInterval์ด๋ผ๋Š” custom Hook์„ ์‚ฌ์šฉํ–ˆ๋‹ค.
๋ฆฌ์•กํŠธ์˜ ๊ธฐ๋ณธ Hook์ธ setInterval์„ ํ™œ์šฉํ•ด ํƒ€์ด๋จธ๋ฅผ ๊ตฌํ˜„ํ•  ๊ฒฝ์šฐ, ํƒ€์ด๋จธ์˜ ์‹œ๊ฐ„ ํ๋ฆ„๊ณผ ์‹ค์ œ ์‹œ๊ฐ„ ํ๋ฆ„ ์‚ฌ์ด์— ๊ดด๋ฆฌ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค. ์ด๋ฅผ ๋ณด์™„ํ•ด ๋งŒ๋“  ๊ฒŒ useInterval์ธ ๊ฒƒ ๊ฐ™๋‹ค.

 

setInterval์˜ ๊ธฐ๋ณธ ๋™์ž‘์€ ์„ค์ •ํ•œ ์‹œ๊ฐ„๋งˆ๋‹ค ํ•œ ๋ฒˆ์”ฉ ์ฝœ๋ฐฑํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ๋”ฐ๋ผ์„œ useInterval์„ ์‚ฌ์šฉํ•ด 1000ms๋งˆ๋‹ค ์‹œ๊ฐ„์„ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ–ˆ๋‹ค.

 

์ž์„ธํ•œ ์„ค๋ช…์€ ์š”๊ธฐ Making setInterval Declarative with React Hooks

 

๋˜ moment.js ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ duration object๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค. moment.js๋Š” ์ด ํ”Œ์ ํ•˜๋ฉด์„œ ์ฒ˜์Œ์œผ๋กœ ์•Œ๊ฒŒ ๋œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฐ๋ฐ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ ๋‚ ์งœ์™€ ์‹œ๊ฐ„์„ ๋‹ค๋ฃฐ ๋•Œ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ผ๊ณ  ํ•œ๋‹ค. ํฌ๋งคํŒ…์ด๋ผ๋˜์ง€, ๋‹จ์œ„๊ฐ„ ๋ณ€ํ™˜ ๋“ฑ์˜ ์ž‘์—…์„ ์†์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ค€๋‹ค. duration์€ ๋ง๊ทธ๋Œ€๋กœ a length of time์„ ๋œปํ•˜๋Š” ๊ฐ์ฒด์ด๋‹ค. ์ฝ˜์†”์— duration ๊ฐ์ฒด๋ฅผ ์ฐ์–ด๋ณด๋ฉด PT1S PT2M30S ์ด๋Ÿฐ ์‹์œผ๋กœ ์ƒ๊ฒผ์Œ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

const [time, setTime] = useState(moment.duration(0,'seconds'));
const tick = () => {
  setTime(prevTime => prevTime.clone().add(1, 'seconds'));
};
const timer = useInterval(() => {
  tick();
}, 1000);

์‹œ๊ฐ„์ด 1์ดˆ ์ฆ๊ฐ€ํ•  ๋•Œ๋งˆ๋‹ค ํ™”๋ฉด์— ๋ฐ˜์˜๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ state๋กœ ์ •์˜ํ–ˆ๋‹ค.

์ผ์‹œ์ •์ง€ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด ํƒ€์ด๋จธ๋„ ์ •์ง€

์ด๊ฑธ ๋‹ค๋ฅด๊ฒŒ ์ด์•ผ๊ธฐํ•˜๋ฉด, ํ™”๋ฉด์— ํฌ์ปค์Šค๊ฐ€ ์žกํ˜”์„ ๋•Œ์—๋งŒ ํƒ€์ด๋จธ๋ฅผ ๋™์ž‘์‹œ์ผœ์•ผ ํ•œ๋‹ค๋Š” ๋œป์ด๋‹ค.
ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์‚ฌ์šฉ์ž์˜ ํ™”๋ฉด์— ๋– ์žˆ๋Š”์ง€๋ฅผ ์•Œ์•„๋‚ด์•ผ ํ–ˆ๋‹ค.

ํ™”๋ฉด์— ํฌ์ปค์Šค๊ฐ€ ์žกํž˜ -> ํƒ€์ด๋จธ ์‹œ์ž‘/์žฌ๊ฐœ
ํ™”๋ฉด์— ํฌ์ปค์Šค ์‚ฌ๋ผ์ง -> ํƒ€์ด๋จธ ์ค‘์ง€

ํ™”๋ฉด์— ํฌ์ปค์Šค๊ฐ€ ์žกํžˆ๋Š” ๊ฒƒ๊ณผ ์‚ฌ๋ผ์ง€๋Š” ๊ฒƒ์„ ๋ชจ๋‘ ์บ์น˜ํ•ด์•ผ ํ–ˆ๋‹ค.

 

focus๋ผ๋Š” state๋ฅผ ๋‘ฌ์„œ ํ™”๋ฉด์ด ํฌ์ปค์‹ฑ๋˜๋ฉด ๊ฐ’์„ true, ํฌ์ปค์Šค ์•„์›ƒ๋˜๋ฉด false๋กœ ๊ฐ’์„ ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ๊ณ ์ž ํ–ˆ๋‹ค.
focus๊ฐ’์ด true์ผ ๊ฒฝ์šฐ ํƒ€์ด๋จธ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๊ณ , false๋กœ ๋ฐ”๋€” ๊ฒฝ์šฐ clearInterval๋กœ ํƒ€์ด๋จธ๋ฅผ ์ œ๊ฑฐํ–ˆ๋‹ค.

const timer = useInterval(() => {
  if (focus) {
    tick();
  }
}, 1000);

if (!focus) {
  clearInterval(timer);
}

1ํŠธ: useEffect

๊ฒฐ๊ณผ: โŒ
useEffect๋ฅผ ์ด์šฉํ•˜๋ฉด ํ™”๋ฉด์ด ๋ Œ๋”๋ง๋œ ํ›„ ๋งˆ์šดํŠธ๋  ๋•Œ ํŠน์ • ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.
๋ฌธ์ œ๋Š” ๋ฆฌ์•กํŠธ ๋‚ด๋น„๊ฒŒ์ด์…˜์œผ๋กœ ํ™”๋ฉด ์ด๋™์‹œ ์ปดํฌ๋„ŒํŠธ์˜ ๋งˆ์šดํŠธ/์–ธ๋งˆ์šดํŠธ๊ฐ€ ์ด๋ค„์ง€์ง€ ์•Š๋Š”๋‹ค๋Š” ์ ์ด์—ˆ๋‹ค.

RunningScreen ์ปดํฌ๋„ŒํŠธ์—์„œ navigation.push๋ฅผ ํ†ตํ•ด PauseScreen ์ปดํฌ๋„ŒํŠธ๋กœ ์ด๋™ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ด๋ณด์ž. ์ด๋•Œ RunningScreen์€ ์–ธ๋งˆ์šดํŠธ ๋˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ์ฆ‰ ํ™”๋ฉด์—์„œ ์‚ฌ๋ผ์ง€๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ ๊ทธ๋Œ€๋กœ ์žˆ๊ณ  ๊ทธ ์œ„์— PauseScreen์ด ์Œ“์ด๋Š” ๊ฒƒ์ด๋‹ค.

๋”ฐ๋ผ์„œ useEffect๋กœ๋Š” ํ™”๋ฉด์˜ ํฌ์ปค์‹ฑ์„ ๊ฐ์ง€ํ•  ์ˆ˜ ์—†์—ˆ๋‹ค.

2ํŠธ: useFocusEffect

๊ฒฐ๊ณผ: โŒ
์œ„์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” Hook์ด๋‹ค. ์šฉ๋„๋Š” ์ ํ•ฉํ–ˆ๋Š”๋ฐ, ํƒ€์ด๋จธ์˜ ์กด์žฌ๊ฐ€ ๋ฌธ์ œ๊ฐ€ ๋๋‹ค.
ํƒ€์ด๋จธ ๋•Œ๋ฌธ์— 1์ดˆ ๋งˆ๋‹ค RunningScreen์˜ ๋ฆฌ๋ Œ๋”๋ง์ด ๋ฐœ์ƒํ•˜๋Š”๋ฐ, ๋ฆฌ๋ Œ๋”๋ง๋  ๋•Œ๋งˆ๋‹ค useFocusEffect์•ˆ์— ์ž‘์„ฑํ•œ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋๋‹ค. 1์ดˆ๊ฐ€ ์ฆ๊ฐ€ํ•  ๋•Œ๋งˆ๋‹ค useFocusEffect์— ์ž‘์„ฑํ•œ ์ฝœ๋ฐฑํ•จ์ˆ˜์™€ ๋ฆฌํ„ดํ•จ์ˆ˜๊ฐ€ ์—ฐ๋‹ฌ์•„ ํ˜ธ์ถœ๋˜์–ด ํƒ€์ด๋จธ๊ฐ€ ์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์•˜๋‹ค.

(์ง€๊ธˆ ๋‹ค์‹œ ์ƒ๊ฐํ•ด๋ณด๋‹ˆ ํƒ€์ด๋จธ๋ฅผ ๋ณ„๋„์˜ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌํ•ด ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ ๋‚ด์—์„œ๋งŒ ๋ฆฌ๋ Œ๋”๋ง์ด ์ผ์–ด๋‚˜๊ฒŒ ํ•˜๊ฑฐ๋‚˜, focus state๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๋กœ์ง์„ useCallback์œผ๋กœ ์ž‘์„ฑํ•ด๋„ ๋์„ ๊ฒƒ ๊ฐ™๋‹ค. ๊ทธ๋• ์ด ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐ์ง€ ๋ชปํ–ˆ๋‹ค.)

3ํŠธ: navigation.addListener

๊ฒฐ๊ณผ: โœ…

navigation.addListener๋ฅผ ์‚ฌ์šฉํ•˜๋‹ˆ ๋”ฑ ํ™”๋ฉด์— ํฌ์ปค์Šค์™€ ์žกํ˜”์„ ๋•Œ, ํฌ์ปค์Šค ์•„์›ƒ ๋์„ ๋•Œ๋งŒ ์›ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์ƒํƒœ ์—…๋ฐ์ดํŠธ๋กœ ์ธํ•œ ๋ฆฌ๋ Œ๋”๋ง ์‹œ์—๋Š” ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์•˜๋‹ค.

useEffect๋ฅผ ์‚ฌ์šฉํ•ด ์ปดํฌ๋„ŒํŠธ ๋งˆ์šดํŠธ ์‹œ์— addListener๋ฅผ ๋ถ™์—ฌ์คฌ๋‹ค.

useEffect(() => {
  navigation.addListener('focus', e => {
    setFocus(true);
    getLocationUpdates();
  });
  navigation.addListener('blur', e => {
    setFocus(false);
    removeLocationUpdates();
  });
}, [navigation]);

์ฝ”๋“œ ์ „๋ฌธ

  const [time, setTime] = useState(moment.duration(0, 'seconds'));
  const [focus, setFocus] = useState(true);
  const tick = () => {
    setTime(prevTime => prevTime.clone().add(1, 'seconds'));
  };

  const timer = useInterval(() => {
    if (focus) {
      tick();
    }
  }, 1000);

  if (!focus) {
    clearInterval(timer);
  }

  useEffect(() => {
    navigation.addListener('focus', e => {
      setFocus(true);
      getLocationUpdates();
    });
    navigation.addListener('blur', e => {
      setFocus(false);
      removeLocationUpdates();
    });
  }, [navigation]);

๋ฆฌํŒฉํ† ๋ง์— ๋Œ€ํ•œ ๋‹ˆ์ฆˆ๋„, ํ• ๋งŒํ•œ ์—ฌ์œ ๋„ ์—†๋‹ค๋Š” ๊ฒŒ ์ด๋Ÿฐ ํ”Œ์ ์˜ ์•„์‰ฌ์›€์ธ ๊ฒƒ ๊ฐ™๋‹ค.
๊ทธ๋ž˜๋„ ์ด๋ ‡๊ฒŒ ์ •๋ฆฌํ•˜๋Š” ๊ณผ์ •์—์„œ ๋” ๋‚˜์€ ๋ฐฉ์•ˆ์„ ๋– ์˜ฌ๋ ค๋ณผ ์ˆ˜ ์žˆ๋Š” ๊ฒŒ ์ข‹์€๋“ฏ ใ…Žใ…Ž