๐Ÿ‘ค TradeProfile ๊ตฌํ˜„๊ธฐ โ€“ ๊ฑฐ๋ž˜ ๊ฒŒ์‹œ๊ธ€์—์„œ ์œ ์ € ํ”„๋กœํ•„๋กœ ์—ฐ๊ฒฐํ•˜๊ธฐ

์กฐ์ค€ํ˜•ยท2025๋…„ 4์›” 11์ผ
0

CHOP!

๋ชฉ๋ก ๋ณด๊ธฐ
17/20
post-thumbnail

์ด๋ฒˆ์—๋Š” ๊ฒŒ์‹œ๊ธ€์—์„œ ํ•ด๋‹น ์œ ์ €์˜ ํ”„๋กœํ•„๋กœ ์ด๋™ํ•ด ๊ฑฐ๋ž˜ ์ƒํ™ฉ์„ ํ™•์ธํ•˜๊ณ , ๋ฐ”๋กœ ๋Œ€ํ™”๋ฅผ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” TradeProfile ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ–ˆ๋‹ค. ๋‹จ์ˆœํ•œ ํ”„๋กœํ•„ ํ™”๋ฉด์ด ์•„๋‹ˆ๋ผ, ๊ฑฐ๋ž˜ ์ „์šฉ ํ”„๋กœํ•„ ๋ทฐ๋ฅผ ๋งŒ๋“œ๋Š” ์ž‘์—…์ด์—ˆ๊ณ , ๊ฑฐ๋ž˜ ๋‹ด๋‹น ํŒ€์›๊ณผ์˜ ํ˜‘์—…์„ ํ†ตํ•ด PostBlock โ†’ TradeProfile๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์—ฐ๊ฒฐ๋˜๋Š” UX ํ๋ฆ„์„ ์™„์„ฑํ–ˆ๋‹ค.

๐Ÿงฉ ์‹œ์ž‘์ : PostBlock ์ปดํฌ๋„ŒํŠธ

๊ฑฐ๋ž˜ ๋ฆฌ์ŠคํŠธ์—์„œ ๊ฐ ๊ฒŒ์‹œ๊ธ€์„ ๋ณด์—ฌ์ฃผ๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” PostBlock์ด์—ˆ๋‹ค. ์ด ์ปดํฌ๋„ŒํŠธ๋Š” ๊ฑฐ๋ž˜ ๋‹ด๋‹น ํŒ€์›์ด ๊ตฌํ˜„ํ•œ ๊ตฌ์กฐ๋กœ, ์šฐ๋ฆฌ๋Š” ์—ฌ๊ธฐ์— ํด๋ฆญ ์‹œ ํ•ด๋‹น ์œ ์ €์˜ TradeProfile๋กœ ์ด๋™ํ•˜๋Š” ๋กœ์ง์„ ์ถ”๊ฐ€ํ–ˆ๋‹ค.

const handleClick = () => {
  const userId: string = post.foreign_ids.user_id;
  const title: string = post.title;
  navigate(`/trade-profile?userID=${userId}&title=${encodeURIComponent(title)}`);
};

useNavigate()๋ฅผ ์‚ฌ์šฉํ•ด ์œ ์ € ID์™€ ๊ฒŒ์‹œ๊ธ€ ์ œ๋ชฉ์„ ์ฟผ๋ฆฌ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ธฐ๊ณ , TradeProfile์—์„œ ์ด๋ฅผ ๋ฐ›์•„์„œ ํ•ด๋‹น ์œ ์ €์˜ ์ •๋ณด์™€ ์ตœ๊ทผ ๊ฑฐ๋ž˜ ๋‚ด์—ญ์„ ๋ถˆ๋Ÿฌ์˜จ๋‹ค.

๐Ÿ›  TradeProfile ๊ตฌ์„ฑ

<ProfileContainer ... />
<TradeStatus ... />
<LatestTrade ... />
<Button>๋Œ€ํ™” ์‹œ์ž‘</Button>

๊ธฐ์กด์— ์“ฐ๋˜ ProfileContainer, TradeStatus ๋“ฑ์„ ์žฌ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌ์กฐ๋ฅผ ๋น ๋ฅด๊ฒŒ ์žก์•˜๋‹ค.

์ตœ๊ทผ ๊ฑฐ๋ž˜ ๋‚ด์—ญ์€ ExchangeData๋ฅผ ํ•„ํ„ฐ๋งํ•ด์„œ 3๊ฐœ์”ฉ ๋ณด์—ฌ์ฃผ๋„๋ก LatestTrade ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋”ฐ๋กœ ๋งŒ๋“ค์—ˆ๋‹ค.

const exchangeWing = GetExchangePostByFilterWing(exchangeParam);
const exchangeResponse = await shootingStar.launch(exchangeWing);
setPosts(exchangeResponse.data.items);

โ†’ ์œ ์ €์˜ ๊ฑฐ๋ž˜ ๋‚ด์—ญ์„ ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์™€์„œ ๊ฑฐ๋ž˜ ์ƒํƒœ์™€ ํ•จ๊ป˜ ํ‘œ์‹œํ–ˆ๋‹ค.

๐Ÿ” ์ปดํฌ๋„ŒํŠธ ์žฌ์‚ฌ์šฉ์œผ๋กœ ๊ฐœ๋ฐœ ํšจ์œจ์„ฑ ํ–ฅ์ƒ

  • ProfileContainer, TradeStatus๋Š” ๊ธฐ์กด Profile ํŽ˜์ด์ง€์—์„œ ์“ฐ์ด๋˜ ๊ฒƒ์„ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉ

  • getImagePathFromProfile() ์—ญ์‹œ ๊ธฐ์กด ์œ ํ‹ธํ•จ์ˆ˜๋ฅผ ๊ทธ๋Œ€๋กœ ํ™œ์šฉ

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

๐Ÿ’ฌ ํ˜‘์—… ํฌ์ธํŠธ

์ด ์ž‘์—…์€ ํ˜ผ์ž์„œ ํ•œ ๊ฒŒ ์•„๋‹ˆ๋ผ, ๊ฑฐ๋ž˜ ๊ฒŒ์‹œํŒ์„ ๋‹ด๋‹นํ•œ ํŒ€์›๊ณผ ํ•จ๊ป˜ ์ž‘์—…ํ•œ ๊ฒฐ๊ณผ๋ฌผ์ด๋‹ค.

  • PostBlock ๋‚ด๋ถ€ ๊ตฌ์กฐ๋ฅผ ๋จผ์ € ํŒŒ์•…ํ•˜๊ณ , ํด๋ฆญ ์‹œ navigate ์ฒ˜๋ฆฌ ๋กœ์ง์„ ์ถ”๊ฐ€

  • ์„œ๋กœ post.foreign_ids.user_id๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ์‹์— ํ•ฉ์˜

  • ๊ฑฐ๋ž˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๋Š” API ๊ตฌ์กฐ๋„ ๋งž์ถฐ์„œ ํ†ตํ•ฉ

์ด ๊ณผ์ •์„ ํ†ตํ•ด ์šฐ๋ฆฌ ํŒ€์˜ ์ฝ”๋“œ ์Šคํƒ€์ผ์ด๋‚˜ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๊ฐ€ ์ ์  ํ†ต์ผ๋˜๋Š” ๋А๋‚Œ์„ ๋ฐ›์•˜๋‹ค.

โš™๏ธ ๊ฐœ๋ฐœํ•˜๋ฉด์„œ ๋А๋‚€ ์  โ€“ Props์™€ Navigation์˜ ์ค‘์š”์„ฑ

๐Ÿ”— Props๋ฅผ ํ†ตํ•œ ๋ฐ์ดํ„ฐ ์ „๋‹ฌ์˜ ํ•ต์‹ฌ์„ฑ

์ด๋ฒˆ TradeProfile ๊ฐœ๋ฐœ์—์„œ ๊ฐ€์žฅ ํฌ๊ฒŒ ๋А๋‚€ ์  ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐ”๋กœ props์˜ ์ค‘์š”์„ฑ์ด์—ˆ๋‹ค.

์ปดํฌ๋„ŒํŠธ ๊ฐ„์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ฒจ์ค„ ๋•Œ props๋Š” ๊ฐ€์žฅ ๊ธฐ๋ณธ์ด์ž ๊ฐ•๋ ฅํ•œ ์ˆ˜๋‹จ์ด๋‹ค.

๋ถ€๋ชจ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ฐ’์„ ๋„˜๊ธฐ๊ณ , ์ž์‹ ์ปดํฌ๋„ŒํŠธ๋Š” ์ด๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ UI๋ฅผ ๊ตฌ์„ฑํ•˜๊ฑฐ๋‚˜ ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด TradeProfile ๋‚ด๋ถ€์—์„œ ProfileContainer๋‚˜ TradeStatus ๊ฐ™์€ ๊ธฐ์กด ์ปดํฌ๋„ŒํŠธ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋„, ์œ ์ € ์ •๋ณด๋‚˜ ํ†ต๊ณ„ ๋ฐ์ดํ„ฐ๋“ค์„ props๋กœ ๋„˜๊ฒจ์ฃผ๋Š” ๊ตฌ์กฐ๋กœ ๋งŒ๋“ค์—ˆ๋‹ค.

๐Ÿš€ navigate๋กœ URL ํŒŒ๋ผ๋ฏธํ„ฐ ๋„˜๊ธฐ๊ธฐ

์ด๋ฒˆ ์ž‘์—…์—์„œ๋Š” React Router์˜ navigate() ํ•จ์ˆ˜๋กœ URL์— ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ฒจ์ฃผ๋Š” ๋ฐฉ๋ฒ•๋„ ํ™œ์šฉํ–ˆ๋‹ค:

navigate(`/trade-profile?userID=${userId}&title=${encodeURIComponent(title)}`);

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํŽ˜์ด์ง€ ์ด๋™๊ณผ ๋™์‹œ์— userID, title ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์œผ๋กœ ๋„˜๊ธธ ์ˆ˜ ์žˆ๋‹ค.

TradeProfile ์ปดํฌ๋„ŒํŠธ์—์„œ๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ location.search๋ฅผ ์‚ฌ์šฉํ•ด ๋ธŒ๋ผ์šฐ์ €์˜ ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์„ ์ง์ ‘ ํŒŒ์‹ฑํ–ˆ๋‹ค:

const params = new URLSearchParams(location.search);
const userId = params.get("userID");
const title = params.get("title");

์—ฌ๊ธฐ์„œ ํ•ต์‹ฌ์€ location.search๋ฅผ ์ด์šฉํ•ด ํ˜„์žฌ ๋ธŒ๋ผ์šฐ์ € ์ฃผ์†Œ์˜ ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์„ ๊ฐ€์ ธ์˜ค๊ณ ,
๊ทธ๊ฑธ URLSearchParams๋ฅผ ํ†ตํ•ด ํŒŒ์‹ฑ(parsing)ํ•ด์„œ ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ํ‚ค(key) ๊ธฐ๋ฐ˜์œผ๋กœ ๊บผ๋‚ธ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

์ด๋•Œ์˜ key๋Š” URL์—์„œ ?userID=junhyeong123&title=๋ ˆ์ „ํ…œํŒ๋งค์ค‘ ๊ฐ™์ด ์ƒ๊ธด ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์˜ ๊ตฌ์กฐ์—์„œ userID, title๊ณผ ๊ฐ™์€ ์ด๋ฆ„์„ ์˜๋ฏธํ•œ๋‹ค.

๊ฐ๊ฐ์˜ key์— ๋Œ€์‘ํ•˜๋Š” value๋Š” "junhyeong123", "๋ ˆ์ „ํ…œํŒ๋งค์ค‘"์ฒ˜๋Ÿผ ์ €์žฅ๋œ ๊ฐ’์ด๊ณ , ์ด ๊ฐ’์„ .get("key")๋กœ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

  • params.get("userID") โ†’ ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์—์„œ userID ๊ฐ’์„ ๊ฐ€์ ธ์˜ด

  • params.get("title") โ†’ ๊ฒŒ์‹œ๊ธ€ ์ œ๋ชฉ์„ ๊ฐ€์ ธ์˜ด

์ด๋ ‡๊ฒŒ ํŒŒ์‹ฑํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ๊ฐ ๋ณ€์ˆ˜๋กœ ์„ ์–ธํ•ด ์ดํ›„ API ์š”์ฒญ์— ํ™œ์šฉํ•˜๊ฑฐ๋‚˜, ํ™”๋ฉด ๊ตฌ์„ฑ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

location.search๋Š” ํ˜„์žฌ URL์˜ ?userID=...&title=... ๊ฐ™์€ ์ฟผ๋ฆฌ์ŠคํŠธ๋ง์„ ๊ฐ€์ ธ์˜ค๊ณ ,
URLSearchParams๋Š” ์ด๋ฅผ ํ‚ค-๊ฐ’ ํ˜•ํƒœ๋กœ ํŒŒ์‹ฑํ•ด์ค€๋‹ค.

์ด ๋ฐฉ์‹์€ React Router์—์„œ ์ œ๊ณตํ•˜๋Š” useSearchParams()๋ฅผ ๊ตณ์ด ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ๋„, ํ•„์š”ํ•œ ๊ฐ’๋งŒ ๊ฐ„๋‹จํ•˜๊ฒŒ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐ ๋งค์šฐ ์œ ์šฉํ–ˆ๋‹ค.

๋ณต์žกํ•œ ์ƒํƒœ ๊ด€๋ฆฌ ์—†์ด, ๊ฐ€๋ณ๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๋„˜๊ฒจ์ฃผ๋Š” ๋ฐ ๋งค์šฐ ์œ ์šฉํ•œ ๋ฐฉ์‹์ด์—ˆ๋‹ค.

๐Ÿ“Œ ํšŒ๊ณ 

๊ฑฐ๋ž˜ UX๋ฅผ ํ•œ ๋‹จ๊ณ„ ๋Œ์–ด์˜ฌ๋ฆฐ ๊ฒฝํ—˜

๋‹จ์ˆœํžˆ ์ •๋ณด๋งŒ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ๊ฒŒ์‹œ๊ธ€ โ†’ ์œ ์ € ํ”„๋กœํ•„ โ†’ ๊ฑฐ๋ž˜ ๋‚ด์—ญ โ†’ ๋Œ€ํ™” ์‹œ์ž‘์ด๋ผ๋Š” ํ๋ฆ„์ด ๋Š๊ธฐ์ง€ ์•Š๋„๋ก ์‹ ๊ฒฝ ์“ด ๊ตฌ์กฐ์˜€๋‹ค.

๋˜ํ•œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฌด๋ถ„๋ณ„ํ•˜๊ฒŒ ์ƒˆ๋กœ ๋งŒ๋“œ๋Š” ๋Œ€์‹ , ๊ธฐ์กด ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ™•์žฅ/์žฌ์‚ฌ์šฉํ•˜๋ฉด์„œ ์œ ์ง€๋ณด์ˆ˜๋„ ์‰ฌ์šด ๊ตฌ์กฐ๋กœ ๋ฐœ์ „์‹œ์ผฐ๋‹ค๋Š” ์ ์ด ๋งŒ์กฑ์Šค๋Ÿฌ์› ๋‹ค.

์•ž์œผ๋กœ๋„ ํ˜‘์—… ์‹œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ ์„ค๊ณ„์™€ ๋ช…ํ™•ํ•œ ์ฑ…์ž„ ๋ถ„๋ฆฌ๋ฅผ ๊ณ„์† ์‹ ๊ฒฝ ์จ์•ผ๊ฒ ๋‹ค.

profile
์ฝ”๋ฆฐ์ด

0๊ฐœ์˜ ๋Œ“๊ธ€