๐Ÿš€ ํ”„๋กœ์ ํŠธ ์„ค๋ช…

  • ๋ณธ ํ”„๋กœ์ ํŠธ๋Š” API ์ฝœ ์ตœ์ ํ™”๋ฅผ ์ ์šฉํ•œ ๊ฒ€์ƒ‰์–ด ์กฐํšŒ ์›น ์‚ฌ์ดํŠธ ์ž…๋‹ˆ๋‹ค.

๐Ÿ’ป ์‹ค์ œ ๊ตฌํ˜„ ํ™”๋ฉด

  • ๋ฉ”์ธ ํ™”๋ฉด

  • ๊ฒ€์ƒ‰ ์‹œ ํ™”๋ฉด


โš’๏ธ ์ฃผ์š” ๊ธฐ๋Šฅ ๊ตฌํ˜„

  • API ์ฝœ ์ตœ์ ํ™”

    • ๊ฒ€์ƒ‰ ์„œ๋น„์Šค๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•  ๋•Œ๋งˆ๋‹ค API ์ฝœ์„ ์š”์ฒญํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋น„ํšจ์œจ์ ์ผ ์ˆ˜ ์žˆ์–ด, ์ด๋ฅผ ์ตœ์ ํ™”
    • ๋‹จ, axios๋งŒ ์‚ฌ์šฉ ๊ฐ€๋Šฅ(axios์˜ cache ์˜ต์…˜ X, react-query์™€ ๊ฐ™์€ ์บ์‹ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ X)
  • ์ตœ๊ทผ ๊ฒ€์ƒ‰์–ด ๊ธฐ๋Šฅ

    • ์ตœ๊ทผ ๊ฒ€์ƒ‰์–ด ์ตœ๋Œ€ 5๊ฐœ
    • 5๊ฐœ ์•ˆ์— ์ค‘๋ณต๋œ ๊ฒ€์ƒ‰์–ด ์žˆ์„ ๊ฒฝ์šฐ, ์ƒˆ๋กœ ์ถ”๊ฐ€ X โžก๏ธ ๊ธฐ์กด์— ์žˆ๋˜ ๊ฒ€์ƒ‰์–ด๊ฐ€ ๊ฐ€์žฅ ์ฒซ ๋ฒˆ์งธ๋กœ ์ด๋™
    • 5๊ฐœ๊ฐ€ ๋„˜์—ˆ์„ ๋•Œ ์ƒˆ๋กœ์šด ๊ฒ€์ƒ‰์–ด๊ฐ€ ์ถ”๊ฐ€๋˜๋ฉด, ๊ฐ€์žฅ ๋งˆ์ง€๋ง‰ ๊ฒ€์ƒ‰์–ด ์‚ญ์ œ
    • ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋Š” ์›น ํŽ˜์ด์ง€ ์ข…๋ฃŒ ํ›„์—๋„ ์œ ์ง€๋˜๋„๋ก
  • ํ‚ค๋ณด๋“œ ๋งŒ์œผ๋กœ ์ถ”์ฒœ ๊ฒ€์ƒ‰์–ด ๋ฐ ์ผ๋ฐ˜ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ

    • ํ‚ค๋ณด๋“œ ๋งŒ์œผ๋กœ ์ƒํ•˜ ์ด๋™, ENTER๋กœ ๊ฒ€์ƒ‰
    • ๋งˆ์šฐ์Šค ํด๋ฆญ์œผ๋กœ๋„ ๊ฒ€์ƒ‰์–ด๋กœ ๊ฒ€์ƒ‰ ๊ฐ€๋Šฅ
    • ๊ฒ€์ƒ‰ ์‹œ ๋ณ„๋‹ค๋ฅธ ํŽ˜์ด์ง€ ์ด๋™ ์—†์ด ์ตœ๊ทผ ๊ฒ€์ƒ‰์–ด๊ฐ€ ์ถ”๊ฐ€๋˜๋Š” ํ˜•ํƒœ
  • ๊ฒ€์ƒ‰ ๋‹จ์–ด ํ•˜์ด๋ผ์ดํŠธ

    • ๊ฒ€์ƒ‰์–ด๊ฐ€ ํฌํ•จ๋œ ๋ถ€๋ถ„์„ ํ•˜์ด๋ผ์ดํŠธ

โœจ API ์ฝœ ์ตœ์ ํ™” ๋ฐฉ๋ฒ• - Debouncing

  • API ์ฝœ ์ตœ์ ํ™” ๋ฐฉ๋ฒ•์œผ๋กœ๋Š” ์“ฐ๋กœํ‹€๋ง, ๋””๋ฐ”์šด์‹ฑ, API ์บ์‹œ, axios์—์„œ ๊ด€๋ จ ์„ค์ •, ์บ์‹ฑ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ ๋“ฑ ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

    • ์“ฐ๋กœํ‹€๋ง : ๋งˆ์ง€๋ง‰ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋œ ํ›„ ์ผ์ • ์‹œ๊ฐ„์ด ์ง€๋‚˜๊ธฐ ์ „์— ๋‹ค์‹œ ํ˜ธ์ถœ๋˜์ง€ ์•Š๋„๋ก ํ•˜๋Š” ๊ฒƒ
    • ๋””๋ฐ”์šด์‹ฑ : ์—ฐ์ด์–ด ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜๋“ค ์ค‘ ๋งˆ์ง€๋ง‰ ํ•จ์ˆ˜(๋˜๋Š” ์ œ์ผ ์ฒ˜์Œ)๋งŒ ํ˜ธ์ถœํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ

    ๐Ÿ‘‰ ์ €๋Š” ์ด ์ค‘ ๋””๋ฐ”์šด์‹ฑ ๋ฐฉ๋ฒ•์„ ์ฑ„ํƒํ•˜์—ฌ ๋ณธ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ๋ฐฉ๋ฒ•์€ ํƒํ•œ ์ด์œ ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    • ์„ค์ •ํ•œ ํŠน์ • ์‹œ๊ฐ„ ์ฃผ๊ธฐ๋กœ ๊ณ„ ์‹คํ–‰๋˜๋Š” ์“ฐ๋กœํ‹€๋ง ๋ฐฉ์‹๋ณด๋‹ค๋Š”
      ์ด๋ฒคํŠธ๊ฐ€ ์—ฐ์†์ ์œผ๋กœ ๋ฐœ์ƒํ•˜๋”๋ผ๋„ ์„ค์ •ํ•œ ํŠน์ • ์‹œ๊ฐ„ ๋™์•ˆ์€ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๊ณ , ๋งจ ๋งˆ์ง€๋ง‰ ์ด๋ฒคํŠธ์—์„œ ๋ฐœ์ƒ์‹œํ‚ค๋Š” ๋””๋ฐ”์šด์‹ฑ ๋ฐฉ์‹์„ ๊ฒ€์ƒ‰ ๊ธฐ๋Šฅ์— ์ ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋งž๋‹ค๊ณ  ํŒ๋‹จํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์ ์šฉํ•œ ๋ฐฉ์‹ ์„ค๋ช…

  ๐Ÿ“œ Hooks/useDebounce.js
  
  const useDebounce = (value, delay) => {
	const [debounceValue, setDebounceValue] = useState(value)

	useEffect(() => {
		const handler = setTimeout(() => {
			setDebounceValue(value)
		}, delay)
		return () => clearTimeout(handler)
	}, [value, delay])

	return debounceValue
	
  ------------------------------------------------------------------

  ๐Ÿ“œ App.js
  
  const debounceSearchTerm = useDebounce(searchText, 300)
  
  useEffect(() => {
	getSearchList(debounceSearchTerm) // getSearchList๋Š” API ์š”์ฒญ ๋ณด๋‚ด๋Š” ํ•จ์ˆ˜
  }, [debounceSearchTerm])

  

1) ๊ฒ€์ƒ‰์„ ํ•˜๊ฒŒ ๋˜๋ฉด ํ™”๋ฉด์ด ๋ Œ๋”๋ง๋˜๋ฉด์„œ searchText๊ฐ€ ์ปค์Šคํ…€ ํ›…์—๊ฒŒ ์ „๋‹ฌ๋œ๋‹ค.

2) 1์— ์˜ํ•ด ์˜์กด์„ฑ ๋ฐฐ์—ด์— debounceSearchTerm์ด ๋‹ด๊ฒจ์žˆ๋Š” useEffect๊ฐ€ ์‹คํ–‰
โžก๏ธ API ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.
โžก๏ธ ๊ทธ๋Ÿฐ๋ฐ ๊ทธ ์š”์ฒญ์€ 0.3์ดˆ ์ดํ›„์— ๋ณด๋‚ด๋„๋ก
โžก๏ธ โ€ป ๊ทธ๋Ÿฐ๋ฐ ์ด delayedSearchState๊ฐ€ ๊ณ„์† ๊ณ„์† ๋ฐ”๋€Œ๊ฒŒ ๋˜๋ฉด timer๊ฐ€ ์ƒ๊ธฐ๊ณ  api ์š”์ฒญ์ด ์ด๋ฃจ์–ด์ง€๊ธฐ๋„ ์ „์— ์ง€์›Œ์ง€๊ณ ๋ฅผ ๋ฐ”๋กœ ํ•˜๋‹ค๋ณด๋‹ˆ
==> ๊ฒฐ๋ก ์ ์œผ๋กœ๋Š” ์ž…๋ ฅ์ด ๋ฉˆ์ถ˜ ํ›„ 0.3์ดˆ ๋™์•ˆ ๊ธฐ๋‹ค๋ฆฐ ํ›„์— API ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค

==> ๊ฒฐ๋ก ์ ์œผ๋กœ onChange ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋–„๋งˆ๋‹ค
    ๋งค๋ฒˆ API ์š”์ฒญ์„ ๋ณด๋‚ด์ง€ ์•Š๊ณ , ์ผ์ • term์„ ๋‘๊ณ  ์š”์ฒญ์„ ๋ณด๋‚ธ๋‹ค.
    ๋„ˆ๋ฌด ๋งŽ์€ ์ด๋ฒคํŠธ๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š์•„ ๊ณผ๋„ํ•œ API ์ฝœ์„ ํ•˜์ง€ ์•Š์•„ ์„ฑ๋Šฅ ๊ฐœ์„ ์—๋„ ๋„์›€์ด ๋œ๋‹ค.
 
==> ํŠนํžˆ, ์‚ฌ์šฉ๊ฐ์—๋„ ํฐ ๋ถˆํŽธ์ด ์—†์—ˆ๋‹ค.

search_1

  • ํŠน์ • ๊ตฌ๊ฐ„์— ๊ฒ€์ƒ‰์–ด๋ฅผ ์ž…๋ ฅํ•  ๊ฒฝ์šฐ API ์š”์ฒญ์„ ๋ณด๋‚ด์ง€ ์•Š๊ณ , ๋งˆ์ง€๋ง‰ ์ด๋ฒคํŠธ์—์„œ๋งŒ API ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด ์•„๋‹Œ, ํŠน์ • ๊ตฌ๊ฐ„์—์„œ๋งŒ API ์š”์ฒญ์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

๐Ÿ” CORS ์—๋Ÿฌ ์ •์˜

CORS(Cross Origin Resource Sharing)

CORS๋Š” ๋‹ค๋ฅธ ๋„๋ฉ”์ธ์„ ๊ฐ€์ง„ ๋ฆฌ์†Œ์Šค์— ์—‘์„ธ์Šคํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๋ณด์•ˆ ๋ฉ”์ปค๋‹ˆ์ฆ˜

๐Ÿ‘‰ ์•„๋ฌด๋‚˜ ์šฐ๋ฆฌ ์„œ๋ฒ„์— ์š”์ฒญ์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ๋‹ค๋ฉด, ๋ˆ„๊ตฐ๊ฐ€ ์•…์˜์ ์œผ๋กœ ์„œ๋ฒ„์— ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•ด์ง„๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €์—์„œ๋Š” ํ˜„์žฌ ์žˆ๋Š” ๋„๋ฉ”์ธ/ํฌํŠธ์™€ ๋‹ค๋ฅธ ๊ณณ์œผ๋กœ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์„ ์›์ฒœ์ ์œผ๋กœ ๋ง‰์•„๋†“์Šต๋‹ˆ๋‹ค.

CORS ์—๋Ÿฌ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•

๐Ÿช„ 1. ํด๋ผ์ด์–ธํŠธ์—์„œ ํ•ด๊ฒฐ

  • Proxy ํŒจํ„ด ์ด์šฉ
    ํด๋ผ์ด์–ธํŠธ ์›นํŽ˜์ด์ง€์—์„œ ์ง์ ‘ ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ํด๋ผ์ด์–ธํŠธ ํŽ˜์ด์ง€ -> ํด๋ผ์ด์–ธํŠธ ์„œ๋ฒ„ -> ๋ฐฑ์—”๋“œ ์„œ๋ฒ„
    ๐Ÿ‘‰ ์ค‘๊ฐ„ ๋‹ค๋ฆฌ๋ฅผ ํ•˜๋‚˜ ๋†“๋Š”๋‹ค!
    ๐Ÿ‘‰ ์„œ๋ฒ„์—์„œ ์„œ๋ฒ„๋ผ๋ฆฌ ํ†ต์‹ ํ•  ๋•Œ๋Š” CORS ์ •์ฑ…์ด ์ ์šฉX์„ ์ด์šฉ

๐Ÿช„ 2. ์„œ๋ฒ„(NodeJS)์—์„œ ํ•ด๊ฒฐ

  • ์‘๋‹ต ํ—ค๋”์— Access-Control-Allow-Origin ํ—ค๋”๋ฅผ ์‚ฝ์ž…
  • cors ๋ฏธ๋“ค์›จ์–ด ์‚ฌ์šฉ
  • ์ฟ ํ‚ค ์š”์ฒญ ํ—ˆ์šฉ