๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ‘ฉ๐Ÿป‍๐Ÿ’ป dev

์„ ์–ธ์ ์ธ ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ

๐Ÿ—ฃ๏ธ '์„ ์–ธ์ ์ธ ์ฝ”๋“œ'์— ๋Œ€ํ•ด์„œ ๋“ค์–ด๋ณด์…จ๋‚˜์š”?

 

๋“ค์–ด๋Š” ๋ดค๋Š”๋ฐ.. ๋ญ์ง€?

 

ํ† ์Šค ํ”„๋ก ํŠธ์—”๋“œ ์ฑ•ํ„ฐ์—์„œ๋Š” ์„ ์–ธ์ ์ธ ์ฝ”๋“œ (Declarative Code)๋ฅผ ์ถ”์ƒํ™” ๋ ˆ๋ฒจ์ด ๋†’์•„์ง„ ์ฝ”๋“œ๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.

 

์ถ”์ƒํ™” ๋ ˆ๋ฒจ์ด ๋†’์•„์ง„ ์ฝ”๋“œ๋ž€? 

 

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฐฐ์—ด์˜ ํ•ฉ์„ ๊ตฌํ•˜๋Š” ํ•จ์ˆ˜ sum์„ ์‚ดํŽด๋ณด์ž.

 

sum([1,2,3]);


// sum ํ•จ์ˆ˜์˜ ๊ตฌํ˜„ 

function sum(nums: number[]) {
  let result = 0;

  for (const num of nums) {
    result += num;
  }

  return result;
}

 

sum ํ•จ์ˆ˜์˜ ์ดˆ๊ธฐ๊ฐ’์€ 0์ด๊ณ , for๋ฌธ์„ ๋Œ๋ฉด์„œ ๋ฐฐ์—ด์˜ ๊ฐ ์ˆ˜๋ฅผ ๋”ํ•˜๊ณ ,

๋”ํ•ด์ง„ ๊ฒฐ๊ด๊ฐ’์„ ๋ฆฌํ„ดํ•ด์ค€๋‹ค.

 

์ด ์ž‘์—…์ด ์ถ”์ƒํ™”๋˜์–ด,  sum ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ์€ ๋‚ด๋ถ€์˜ ๋ณต์žกํ•œ ์ œ์–ด ํ๋ฆ„์— ๋Œ€ํ•œ ์ดํ•ด ์—†์ด

๋ฐฐ์—ด์˜ ํ•ฉ์„ ๊ตฌํ•˜๋Š” ๋™์ž‘์— ์ง‘์ค‘ํ•˜์—ฌ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

 

์ฆ‰, ์„ ์–ธ์ ์ธ ์ฝ”๋“œ๋Š” ๋‚ด๋ถ€์˜ ์ œ์–ด ํ๋ฆ„์ด ์ถ”์ƒํ™”๋˜์–ด 

๋™์ž‘์— ์ง‘์ค‘ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

  // for of ๋ฌธ๋„ ์„ ์–ธ์ ์ธ ์ฝ”๋“œ๋‹ค.
  
  for (const num of nums) {
    result += num;
  }
  
  // ๋‚ด๋ถ€์ ์œผ๋กœ ๋ฐฐ์—ด์˜ ๊ฐ ์š”์†Œ๋ฅผ ์ˆœํšŒํ•˜๋Š” ๋™์ž‘์ด ์ถ”์ƒํ™”๋œ ๊ฒƒ์ด๋‹ค.
  
  const iterator = nums[Symbol.iterator](); // Iterator ์ƒ์„ฑํ•˜๊ณ 

    let step;
	
    while (!(step = iterator.next()).done) {	// Iterator๊ฐ€ ์—†์„ ๋•Œ๊นŒ์ง€
      const num = step;		// ๋‹ค์Œ ์š”์†Œ๋ฅผ ์ฐจ๋ก€๋กœ ๊ฐ€์ ธ์˜จ๋‹ค
      /* ๋™์ž‘ ... */
    }
// iterator ์‚ญ์ œ ๋™์ž‘ ์ƒ๋žต..

 

ํ•ญ์ƒ ๋“ค์–ด์™”๋˜ silver bullet์€ ์—†๋‹ค๋Š” ๋ง์€ ์„ ์–ธ์ ์ธ ์ฝ”๋“œ๋ฅผ ์“ธ ๋•Œ์—๋„ ์ ์šฉ๋œ๋‹ค.

ํ† ์Šค์—์„œ๋Š” ์ข‹์€ ์ฝ”๋“œ๋ฅผ ํŒ๋‹จํ•˜๊ธฐ ์œ„ํ•œ ์›์น™๋“ค์ด ์žˆ๋Š”๋ฐ ๊ทธ ์ค‘ ์ œ1์›์น™์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

"์ˆ˜์ •ํ•˜๊ธฐ ์‰ฌ์šด ์ฝ”๋“œ"

 

๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ ์‚ฌํ•ญ์€ ํ•ญ์ƒ ๋น ๋ฅด๊ฒŒ ๋ณ€ํ•˜๊ณ , ๊ฐœ๋ฐœ์ž๋Š” ์ด์— ์‹ ์†ํ•˜๊ฒŒ ๋Œ€์‘์„ ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— 

์„ ์–ธ์  ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•˜๊ธฐ ์‰ฌ์šด ๊ฒฝ์šฐ์™€ ๊ทธ๋ ‡์ง€ ์•Š์„ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

<SignUpForm
  onSubmit={result => {
    /* ํšŒ์›๊ฐ€์ž… ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ์„œ ํŠน์ • ๋™์ž‘ ์ˆ˜ํ–‰ ... */
  }}
/>โ€‹

 

๐Ÿ˜ ์‰ฌ์šด ๊ฒฝ์šฐ : ํšŒ์› ๊ฐ€์ž… ํผ์„ ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ํšจ์œจ์ ์ด๋‹ค.

์žฌ์‚ฌ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, ํ•œ ๊ณณ๋งŒ ์ˆ˜์ •ํ•˜๋ฉด ๋‹ค๋ฅธ ๊ณณ์—๋„ ๋ฐ˜์˜๋˜์–ด ๋น ๋ฅด๊ฒŒ ์ž‘์—…์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

 

๐Ÿ˜– ๊ทธ๋ ‡์ง€ ์•Š์„ ๊ฒฝ์šฐ : ํ™”๋ฉด๋งˆ๋‹ค SignUpForm์ด ์กฐ๊ธˆ์”ฉ ๋‹ค๋ฅด๋‹ค๋ฉด ๊ณตํ†ตํ™”๋œ ๊ฒƒ์ด ์˜คํžˆ๋ ค ์ฝ”๋“œ์˜ ๋ณต์žกํ•จ์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค๋ฉด, SNS ํšŒ์›๊ฐ€์ž…์„ ์ผ๋ฐ˜ ์ด๋ฉ”์ผ ํšŒ์› ๊ฐ€์ž…๋ณด๋‹ค ๋จผ์ € ๋ณด์—ฌ์ค˜์•ผ ํ•˜๊ฑฐ๋‚˜,

ํŽ˜์ด์ง€๋งˆ๋‹ค ํ…์ŠคํŠธ๋‚˜ ์Šคํƒ€์ผ์ด ์กฐ๊ธˆ์”ฉ ๋‹ฌ๋ผ์ ธ์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ์–ด ๋ญ์•ผ vinylify ์นด๋“œ ์ปดํฌ๋„ŒํŠธ์ด์•ผ๊ธฐ ๊ฐ™์€๋ฐ?

 

์•„๋ž˜์™€ ๊ฐ™์ด SignUpForm๋Š” ๋‹จ์ˆœํžˆ ํšŒ์› ๊ฐ€์ž…์„ ๋‹ด๋‹นํ•˜๋Š” ์—ญํ• ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ,

๋ฐ”๋€” ์ˆ˜ ์žˆ๋Š” ๋ถ€๋ถ„๊นŒ์ง€ ๋ฐ˜์˜ํ•ด์„œ ๋‚ด๋ถ€ ๊ตฌํ˜„๊ณผ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋ณต์žกํ•ด์ง€๊ณ , ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ ์ž…์žฅ์—์„œ๋„ ๋ถˆํŽธํ•ด์ง„๋‹ค.

<SignUpForm
  signUpOrder={['sns', 'normal']
  title="์‚ฌ์ดํŠธ์— ์–ด์„œ ์˜ค์„ธ์š”"
  subtitle="๋จผ์ € ํšŒ์›๊ฐ€์ž…์„ ํ•ด์ฃผ์„ธ์š”."
  primaryButtonColor={colors.blue}
  secondaryButtonColor={colors.grey}
  /* ๋งŽ์€ Prop ๋“ค ... */
  onCancel={/* ... */}
  onSubmit={result => {
    /* ํšŒ์›๊ฐ€์ž… ๊ฒฐ๊ณผ์— ๋”ฐ๋ผ์„œ ํŠน์ • ๋™์ž‘ ์ˆ˜ํ–‰ ... */
  }}
/>

 

๋”ฐ๋ผ์„œ, ์„ ์–ธ์ ์ธ ์ฝ”๋“œ๋Š” ์ฝ”๋“œ์˜ ์–ด๋–ค ๋ถ€๋ถ„์ด ์ˆ˜์ •๋ ์ง€ ์˜ˆ์ธกํ•˜๊ณ , ์ ์ ˆํ•œ ์„ ์–ธ ๋ ˆ๋ฒจ์„ ๋”ฐ๋ฅด๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.

 

ํ† ์Šค ํ”„๋ก ํŠธ์—”๋“œ ์ฑ•ํ„ฐ์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์„ ์–ธ์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์œ ํ‹ธ๋ฆฌํ‹ฐ์ธ useOverlay๋ฅผ ์‚ดํŽด๋ณด์ž.

 

const overlay = useOverlay();

// '๋ฐ”ํ…€์‹œํŠธ ์—ด๊ธฐ' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ์œ„์™€ ๊ฐ™์€ overlay๊ฐ€ ์—ด๋ฆฐ๋‹ค.

<button
  onClick={() => {
    overlay.open(({ isOpen, close }) => {
      return (
        <BottomSheet open={isOpen} onClose={close}>
          ๋‚˜๋Š” ๋ฐ”ํ…€์‹œํŠธ์•ผ
        </BottomSheet>
      );
    })
  }}
>
  ๋ฐ”ํ…€์‹œํŠธ ์—ด๊ธฐ
</button>

// useOverLay๊ฐ€ ์—†๋‹ค๋ฉด ์ œ์–ด ํ๋ฆ„์„ ๋…ธ์ถœ์‹œ์ผœ์•ผํ•œ๋‹ค.

const [isSheetOpen, setIsSheetOpen] = useState(false);

<button onClick={() => setIsSheetOpen(true)}>
  ๋ฐ”ํ…€์‹œํŠธ ์—ด๊ธฐ
</button>
<BottomSheet open={isSheetOpen} onClose={() => setIsSheetOpen(false)}>
  ๋‚˜๋Š” ๋ฐ”ํ…€์‹œํŠธ์•ผ
</BottomSheet>

 

 

๋˜ ๋‹ค๋ฅธ ์„ ์–ธ์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์œ ํ‹ธ ์ปดํฌ๋„ŒํŠธ์ธ ImpressionArea๋Š”

์–ด๋–ค ์˜์—ญ์ด ๋ณด์ด๊ฑฐ๋‚˜ ์ˆจ๊ฒจ์ง€๋ฉด ์š”์†Œ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

<ImpressionArea onImpressionStart={() => { /* ๋ณด์—ฌ์กŒ์„ ๋•Œ ์‹คํ–‰ */ }}>
  <div>๋‚ด๊ฐ€ ๋ณด์—ฌ์กŒ์œผ๋ฉด onImpressionStart๊ฐ€ ์‹คํ–‰๋ผ</div>
</ImpressionArea>

// ImpressionArea๋Š” ๋ณต์žกํ•œ IntersectionObserver API๋‚˜
// ๋ณต์žกํ•œ Scroll ์ด๋ฒคํŠธ ํ•ธ๋“ค๋Ÿฌ ๋กœ์ง์„ ์‚ฌ์šฉํ•  ํ•„์š” ์—†์ด ๋ณด์—ฌ์กŒ์„ ๋•Œ์˜ ๋™์ž‘์—๋งŒ ์ง‘์ค‘ํ•˜๋ฉด ๋œ๋‹ค.

 

 ๋งˆ์ง€๋ง‰์œผ๋กœ ํ† ์Šค๋Š” ๋ฐ์ดํ„ฐ ์ฃผ๋„ ์˜์‚ฌ๊ฒฐ์ •์„ ์œ„ํ•ด ํ™”๋ฉด์— ์ง„์ž…ํ•˜๋Š” ์‚ฌ์šฉ์ž์˜ ์ˆ˜,

๊ทธ์ค‘ ๋ช‡ ๋ช…์ด ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋Š” ์ง€๋ฅผ ๊ธฐ๋กํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋Š”๋ฐ,  LoggingClick ์ปดํฌ๋„ŒํŠธ๋Š” 

์ด ๋ˆ„๋ฅด๋Š” ๋™์ž‘์— ๋Œ€ํ•œ ๊ธฐ๋ก์„ ์ถ”์ƒํ™”ํ•˜๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

 

<LoggingClick params={{ price }}>
  <button onClick={buy}>์‚ฌ๊ธฐ</button>
</LoggingClick>

// LoggingClick ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์—†๋‹ค๋ฉด 
<button
  onClick={() => {
    log({ title: '์‚ฌ๊ธฐ', price });
    buy();
  }}
>
  ์‚ฌ๊ธฐ
</button>



๐Ÿ“š References

 

์„ ์–ธ์ ์ธ ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ

์„ ์–ธ์ ์ธ ์ฝ”๋“œ, ํ† ์Šค ํ”„๋ก ํŠธ์—”๋“œ ์ฑ•ํ„ฐ๋Š” ์–ด๋–ป๊ฒŒ ์ƒ๊ฐ์„ ํ•˜๊ณ  ์žˆ์„๊นŒ์š”?

toss.tech

 

useOverlay | Slash libraries

useOverlay๋Š” Overlay๋ฅผ ์„ ์–ธ์ ์œผ๋กœ ๋‹ค๋ฃจ๊ธฐ ์œ„ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ์ž…๋‹ˆ๋‹ค.

www.slash.page

https://www.slash.page/libraries/react/impression-area/src/impressionarea.i18n/

 

๐Ÿค” TMI, ๋Š๋‚€ ์ 

์˜ค๋Š˜์€ ํ† ์Šค๊ฐ€ ์ƒ๊ฐํ•˜๋Š” ์„ ์–ธ์  ์ฝ”๋“œ์— ๋Œ€ํ•ด์„œ ์‚ดํŽด๋ดค๋‹ค.

์ข‹์€ ์„ ์–ธ์  ์ฝ”๋“œ๋Š” ์ถ”์ƒํ™”๊ฐ€ ์ž˜ ๋œ ์ฝ”๋“œ์ด๋‹ค. ์ฆ‰, ๋‚ด๋ถ€ ๋กœ์ง ํ๋ฆ„์„ ํŒŒ์•…ํ•˜๋Š”๋ฐ ์‹ ๊ฒฝ์„ ์“ธ ํ•„์š” ์—†์ด, ๋‚ด๊ฐ€ ํ•˜๊ณ ์ž ํ•˜๋Š”

๋™์ž‘์—๋งŒ ์ง‘์ค‘ํ•˜๋ฉด ๋ผ์„œ ์“ฐ๋Š” ์‚ฌ๋žŒ ์ž…์žฅ์—์„œ ํŽธ๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋‹ค.

ํ•˜์ง€๋งŒ, ์ƒํ’ˆ์ด ์–ด๋–ป๊ฒŒ ํ™•์žฅ๋  ์ง€์— ๋Œ€ํ•œ ๊ณ ๋ฏผ ์—†์ด ์ง€๋‚˜์น˜๊ฒŒ ์ถ”์ƒํ™”๋ฅผ ํ•˜๋ฉด ์ˆ˜์ •ํ•˜๊ธฐ ๋ฒˆ๊ฑฐ๋กญ๊ณ  ์–ด๋ ค์šด ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

์ถ”์ƒํ™”๋ฅผ ํ•  ๋ฒ”์œ„์— ๋Œ€ํ•œ ๊ณ ๋ฏผ์ด ํ•„์š”ํ•œ ๊ฒƒ ๊ฐ™๋‹ค. LoggingClick, ImpressionArea, useOverlay ๋ชจ๋‘ ํ•˜๋‚˜์˜ ์—ญํ• ์„ ๋‹ด๋‹นํ•œ๋‹ค๋Š” ๊ณตํ†ต์ ์ด ์žˆ๋Š” ๊ฑฐ ๊ฐ™๋‹ค.

LoggingClick์€ ํด๋ฆญ ์‹œ ๋กœ๊น…๋งŒ,

ImpressionArea๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ IntersectionObserver๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ์ง€ํ•˜๋Š” ์—ญํ• ๋งŒ, 

useOverlay๋Š” toast ui ๊ฐ™์€ ์—ญํ•  (ํด๋ฆญ ์‹œ์— ํ† ์ŠคํŠธ ๋ณด์—ฌ์ฃผ๊ณ , ๋‹ซ์„ ๋•Œ ์‚ฌ๋ผ์ง€๊ฒŒ ํ•ด ์ฃผ๊ธฐ)์„ ํ•œ๋‹ค.