ETC

์›ํ‹ฐ๋“œ ํ”„๋ฆฌ์˜จ๋ณด๋”ฉ ํ”„๋ก ํŠธ์—”๋“œ ์ฝ”์Šค 1์ฃผ์ฐจ ํšŒ๊ณ  (2)

ttaerrim 2022. 2. 19. 15:46

์ฒซ ๋ฒˆ์งธ ๊ณผ์ œ๋Š” ๊ฐ„๋‹จํ•œ ํ™˜์œจ ๊ณ„์‚ฐ๊ธฐ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ณผ์ œ์˜€๋‹ค.

์šฐ๋ฆฌ ํŒ€์€ ๋„ค ๋ช…์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๊ณ  ์ด๋ฒˆ ๊ณผ์ œ๋Š” ๋‘ ๋ช…์”ฉ ๋‚˜๋‰˜์–ด ํ•˜๋‚˜์˜ ๊ณ„์‚ฐ๊ธฐ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ณผ์ œ์˜€๋‹ค. ๋‚ด๊ฐ€ ๋งก์€ ๋ถ€๋ถ„์€ ์ˆ˜์ทจ ๊ตญ๊ฐ€๋ฅผ ์„ ํƒํ•˜๊ณ  ์†ก๊ธˆ์•ก์„ ์ž…๋ ฅํ•˜๋ฉด ๋ฒ„ํŠผ ํ•˜๋‹จ์— ์ˆ˜์ทจ๊ธˆ์•ก์ด ์ˆ˜์ทจ๊ตญ๊ฐ€์— ๋งž๋Š” ํ™˜์œจ๋กœ ๋ณ€ํ™˜๋˜์–ด ์ถœ๋ ฅ๋˜๋Š” ๊ณ„์‚ฐ๊ธฐ์˜€๋‹ค.

 

์ง€๊ธˆ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด ์ฐธ ์—‰์„ฑํ•˜๋‹ค. ๊ฐ™์ด ํ”„๋ฆฌ์˜จ๋ณด๋”ฉ ์ฝ”์Šค๋ฅผ ์ฐธ์—ฌํ•˜๋Š” ์‚ฌ๋žŒ๋“ค์„ ๋ณด๋ฉด ์ด๋Ÿฐ์ €๋Ÿฐ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋‹ค๋ฃฐ ์ค„ ์•„๋Š” ๋ถ„๋“ค์ด ๋งŽ์ด ๊ณ„์‹ ๋ฐ ๋‚˜๋Š” ์–ด๋–ป๊ฒŒ ํ•ฉ๊ฒฉ์„ ํ•ด์„œ ๋ฐฐ์šฐ๊ณ  ์žˆ๋‚˜ ์‹ถ์„ ์ •๋„๋‹ค. ๋‚ด๊ฐ€ ๋ฌธ ๋‹ซ๊ณ  ๋“ค์–ด์˜จ ๊ฒŒ ์•„๋‹Œ๊ฐ€ ์‹ถ๋‹ค.

 

1. API ํ˜ธ์ถœ

ํ™˜์œจ ์ •๋ณด๋ฅผ ๋ฐ›์•„ ์˜ค๊ธฐ ์œ„ํ•ด API๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค. ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ๊ณ„์‚ฐ๊ธฐ๊ฐ€ ๋‘ ๊ฐ€์ง€์ธ๋ฐ, ๊ฐ™์€ ํ™˜์œจ API ์ •๋ณด๋ฅผ ์“ฐ๊ธฐ ๋•Œ๋ฌธ์— redux toolkit์„ ์‚ฌ์šฉํ•ด ํ™˜์œจ ์ •๋ณด๋Š” ์ „์—ญ ์ƒํƒœ ๊ด€๋ฆฌ๋ฅผ ํ–ˆ๋‹ค. ์ด ๋ถ€๋ถ„์€ ์šฐ๋ฆฌ ํŒ€ ์ข…์› ๋‹˜๊ป˜์„œ ์ž‘์„ฑํ•˜์…จ๋‹ค.

// store/index.js

import { configureStore, createSlice } from "@reduxjs/toolkit";

const exchangeRateSlice = createSlice({
  name: "currency",
  initialState: { exchangeRate: "" },
  reducers: {
    getExchangeRate(state, action) {
      state.exchangeRate = action.payload;
    },
  },
});

const store = configureStore({
  reducer: {
    rate: exchangeRateSlice.reducer,
  },
});

export const exchangeRateActions = exchangeRateSlice.actions;

export default store;

๊ทธ๋ฆฌ๊ณ  App.js์—์„œ fetch๋ฅผ ์ด์šฉํ•ด json ๋ฐ์ดํ„ฐ๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๊ณ , ํ™˜์œจ ์ •๋ณด๋ฅผ exchangeRate์— ์ €์žฅํ•œ๋‹ค.

// App.js

import { useEffect } from "react";
import { useDispatch } from "react-redux";
import { exchangeRateActions } from "./store";

function App() {
  const dispatch = useDispatch();

  const getCurrency = async () => {
    const json = await (
      await fetch(
        `http://api.currencylayer.com/live?access_key=${apiKey}&format=1`
      )
    ).json();
    dispatch(exchangeRateActions.getExchangeRate(json.quotes));
  };

  useEffect(() => {
    getCurrency();
  }, [dispatch]);

  return (
    // ์ƒ๋žต
  );
}

export default App;

 

2. ํ™˜์œจ ์ •๋ณด ๊ฐ€์ ธ์˜ค๊ธฐ

select ๋ฐ•์Šค๋กœ ๊ตญ๊ฐ€๋ฅผ ์„ ํƒํ•  ๋•Œ๋งˆ๋‹ค ํ•ด๋‹นํ•˜๋Š” ๊ตญ๊ฐ€์˜ ํ™˜์œจ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•œ๋‹ค.

<select className={styles.textBox} onChange={handleChangeCountry}>
    <option value="KRW" select="true">ํ•œ๊ตญ(KRW)</option>
    <option value="JPY">์ผ๋ณธ(JPY)</option>
    <option value="PHP">ํ•„๋ฆฌํ•€(PHP)</option>
 </select>
const [nation, setNation] = useState("KRW");

const handleChangeCountry = (event) => {
    setNation(event.target.value);
  };

onChange ์ด๋ฒคํŠธ์— handleChangeCountry ํ•จ์ˆ˜๋ฅผ ์—ฐ๊ฒฐํ•ด ์„ ํƒ ํ•ญ๋ชฉ์ด ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค nation์„ ๋ณ€๊ฒฝํ•ด ์ค€๋‹ค.

  const exchangeRate = useSelector((s) => s.rate.exchangeRate);
  const saveRate = exchangeRate["USD" + nation];

๊ทธ๋ฆฌ๊ณ  useSelector๋กœ ํ™˜์œจ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜จ ๋‹ค์Œ, saveRate์— ํ˜„์žฌ ์„ ํƒํ•œ ๊ตญ๊ฐ€์˜ ํ™˜์œจ ๊ฐ’์„ ์ €์žฅํ•œ๋‹ค.

API์˜ ๊ฐ’์ด USDKRW์ฒ˜๋Ÿผ USD + ๊ตญ๊ฐ€ ํ˜•์‹์œผ๋กœ ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ„์™€ ๊ฐ™์ด ํ™˜์œจ ๊ฐ’์„ ๋ฐ›์•„์˜จ๋‹ค.

<p>
  ํ™˜์œจ:{" "}
  {saveRate?.toLocaleString(undefined, {
    maximumFractionDigits: 2,
    minimumFractionDigits: 2,
  })}{" "}
  {nation}/USD
</p>

๊ทธ๋ฆฌ๊ณ  ํ™”๋ฉด์—๋Š” saveRate์™€ nation์„ ์ด์šฉํ•ด 1,193.88 KRW/USD์™€ ๊ฐ™์€ ํ˜•ํƒœ๋กœ ํ™˜์œจ์„ ์ถœ๋ ฅํ•˜๋ฉด ๋œ๋‹ค.

toLocaleString()์€ ์ˆซ์ž์— 3์ž๋ฆฌ๋งˆ๋‹ค ์ฝค๋งˆ๋ฅผ ์ฐ์–ด ์ฃผ๋Š” ํ•จ์ˆ˜์ธ๋ฐ, ์†Œ์ˆ˜์  ๋‘ ์ž๋ฆฌ๊นŒ์ง€ ์ถœ๋ ฅํ•˜๊ธฐ ์œ„ํ•ด ์˜ต์…˜์„ ์คฌ๋‹ค.

 

๊ณผ์ œ ๋ฆฌ๋ทฐ ์‹œ๊ฐ„์— ์•Œ๊ณ  ์•„์‰ฌ์› ๋˜ ์ ์€, ์†ก๊ธˆ์•ก Input์— ์ˆซ์ž๊ฐ€ ์•„๋‹Œ ๊ฐ’์ด ์˜ค๋ฉด ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๋ฅผ ํ•ด ์ฃผ๋Š” ํ•ญ๋ชฉ์ด ์žˆ์—ˆ๋Š”๋ฐ type="number"๋กœ ์ œํ•œํ•ด ์ˆซ์ž ๊ฐ’๋งŒ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค. ์ด ๋ฐฉ์‹์ด ์•„๋‹Œ type์„ ๊ฒ€์ฆํ•˜๊ณ  number๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ์†ก๊ธˆ์•ก์ด ๋ฐ”๋ฅด์ง€ ์•Š๋‹ค๋Š” ๋ฌธ๊ตฌ๋ฅผ ๋„์›Œ์•ผ ํ–ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์•„๋ž˜์™€ ๊ฐ™์ด ์ˆ˜์ •ํ–ˆ๋‹ค.

{Number(sendMoney) < 0 ||
  Number(sendMoney) > 10000 ||
  isNaN(Number(sendMoney)) ? (
  ์†ก๊ธˆ์•ก์ด ๋ฐ”๋ฅด์ง€ ์•Š์Šต๋‹ˆ๋‹ค
  : (
    ์ˆ˜์ทจ๊ธˆ์•ก์€ ์–ผ๋งˆ์ž…๋‹ˆ๋‹ค
  )}

์ฒซ ๋ฒˆ์งธ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งˆ์น˜๋ฉฐ

์›ํ‹ฐ๋“œ ํ”„๋ฆฌ์˜จ๋ณด๋”ฉ ์ฝ”์Šค์—์„œ ํ•œ ์ฒซ ํ˜‘์—…!์ด๋ผ๋Š” ๊ฒƒ์— ์˜๋ฏธ๋ฅผ ๋‘๊ณ  ์‹ถ๋‹ค. ๋ถ„๋ช… ์„œํˆฐ ๋ถ€๋ถ„์ด ํ›จ์”ฌ ๋งŽ๊ณ , ๋‚˜์ค‘์— ์ฝ”๋“œ๋ฅผ ๋‹ค์‹œ ๋ณด๋ฉด ๋ถ€์กฑํ•œ ๋ถ€๋ถ„์ด ์—ฌ์‹คํžˆ ๋ณด์ผ ๊ฒƒ ๊ฐ™๋‹ค. ๊ทธ๋ ‡์ง€๋งŒ ๋‚ด๊ฐ€ ์„ฑ์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐœํŒ์ด ๋  ๊ฑฐ๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์ด ์ง  ์ฝ”๋“œ๋ฅผ ๋ณด๊ณ  ๋งŽ์€ ๊ฒƒ์„ ๋ฐฐ์šธ ์ˆ˜ ์žˆ์—ˆ๊ณ , ์–ด๋–ค ๋ถ€๋ถ„์ด ๋ชจ์ž๋ž€์ง€ ๊ทธ๋ž˜์„œ ์–ด๋–ค ๋ถ€๋ถ„์„ ๋ณด๊ฐ•ํ•ด์•ผ ํ• ์ง€ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. ์กธ์—…์— ์น˜์—ฌ ์šธ๋ฉฐ ๊ฒจ์ž ๋จน๊ธฐ๋กœ ์ฝ”๋”ฉํ–ˆ์„ ๋•Œ์™€ ๋‹ค๋ฅด๊ฒŒ ๊ฐœ๋ฐœ์ž๋ผ๋Š” ๊ธธ๋กœ ๋“ค์–ด์„œ๊ณ  ์‹ถ๋‹ค๋Š” ๋งˆ์Œ์ด ์กฐ๊ธˆ ๋” ๊ตณ์–ด์ง„ ๊ฒƒ ๊ฐ™๋‹ค. ์•ž์œผ๋กœ๋„ ๋”๋” ์—ด์‹ฌํžˆ ํ•ด ๋ณด๋ ค๊ณ  ํ•œ๋‹ค~

 

 

 

GitHub - ttaerrim/wanted_pre_onboarding_01: <ํ™˜์œจ ๊ณ„์‚ฐ๊ธฐ>

<ํ™˜์œจ ๊ณ„์‚ฐ๊ธฐ>. Contribute to ttaerrim/wanted_pre_onboarding_01 development by creating an account on GitHub.

github.com