์์กด์ฑ ์ฃผ์
์ด๋ผ๊ณ ๋ถ๋ฆฌ๋ฉฐ, ์์กดํ๋ ๊ฐ์ฒด๋ฅผ ๋ถ๋ฆฌํ์ฌ ์ฃผ์
ํ๋ค.
๊ธฐ์กด์ a์ ๋ด๋ถ์ ์๋ b๋ c,e ๋ฑ์ ๊ด๊ณ ์์กด์ฑ์ ๊ฐ์ง๊ณ ์๋ค.
ํ์ง๋ง, ์์กด์ฑ์ฃผ์
์ ์ฌ์ฉํ์ฌ b๋ฅผ a๋ก ๋ถํฐ ๋ถ๋ฆฌํ์ฌ ์ฃผ์
ํ๋ฉด(์์กด๊ด๊ณ ์ญ์ , ์์กด์ฑ์ ๋ถ๋ฆฌ) c,e๋ a์ ์ฃผ์
๋ b์ ๊ด๊ณ์ฑ์ด ํ์ฑ๋๋ฏ๋ก b์์ฒด ๋ณด๋ค๋ a์์ ๊ด๊ณ์ ์ ๊ฒฝ์ฐ๋ฉด ๋๋ค.
- ํ ์คํธ๊ฐ ์ฉ์ดํ๋ค
- ์ฝ๋์ ์ฌ์ฌ์ฉ์ฑ์ ๋์ฌ์ค๋ค
- ๊ฐ์ฒด ๊ฐ ๊ฒฐํฉ๋๋ฅผ ์ค์ฌ์ค๋ค
- ๊ฐ๋ ์ฑ์ด ์ข์์ง๋ค
์ธ๋ถ์ ํต์ ํ๋ API๋ฅผ ์ฐ๊ฒฐํ ๋, ๊ทธ ์ญํ ๋ง ์ํํ๋ ํด๋์ค๋ฅผ ์์ฑํ์ฌ ๋ฐ๋ก ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค. ๋ฐ๋ผ์, ์ฌ๋ฌ API๋ฅผ ์ถ๊ฐํ๊ฑฐ๋, ์์ ์ ๋ถ๋ฆฌ๋์ด ์์ด ์ ์ฐํ ํ์ฉ์ด ๊ฐ๋ฅํ๋ค.
์๋์ ์์์ ๊ฐ์ด const youtube = new Youtube();
์ ํ์์ผ๋ก ์ ๋ฌ์ด ๊ฐ๋ฅํ๋ค.
XMLHttpRequest๋ fetch๋ฅผ ์ฌ์ฉํ๊ธฐ ์ด์ ์ ์ฃผ๋ก ์ฌ์ฉ๋์๋ ๋ฐฉ์์ด๋ฉฐ, ์๋ฒ์ ์ํธ์์ฉ ํ๊ธฐ์ํด ์ฌ์ฉ๋๋ค. XML๋ฟ๋ง ์๋๋ผ ๋ชจ๋ ํํ์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋ ๊ฒ์ด ๊ฐ๋ฅํ๋ค. ํ์ง๋ง, ๊ฐ๊ฐ์ ๋จ๊ฒ๋ณ๋ก ์ด๋ป๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๊ณ ์ฒ๋ฆฌํด์ค ๊ฑด์ง ์ด๋ฒคํธ ๊ธฐ๋ฐ์ผ๋ก ์ค์ ํ์ฌ ์์ฑํ์ฌ์ผ ํ๋ค. MDN ๋ฌธ์ ์ฐธ๊ณ
const xhr = new XMLHttpRequest();
xhr.open("GET", "http://domain/service");
// request state change event
xhr.onreadystatechange = function () {
// request completed?
if (xhr.readyState !== 4) return;
if (xhr.status === 200) {
// request successful - show response
console.log(xhr.responseText);
} else {
// request error
console.log("HTTP error", xhr.status, xhr.statusText);
}
};
// start request
xhr.send();
์ด๋ฒคํธ ๊ธฐ๋ฐ์ผ๋ก ์ค์ ์ ํด์ค์ผ ํ๊ธฐ์ ๊ฐ๋
์ฑ์ด ์ข์ง ์์๊ณ , ๋จ๊ณ๋ณ๋ก ์ฒ๋ฆฌ๊ฐ ํ์ํ๋ค. ๊ทธ์ ๋น์ fetch๋ Promise๋ก ๋ฐํํ์ฌ then, catch์ ๋ฉ์๋ ์ฒด์ด๋์ผ๋ก ๊ฐ๋จํ ์์ฑ์ด ๊ฐ๋ฅํ๋ค. ๋ค๋ง, ๋คํธ์ํฌ ์ํ์ฝ๋๊ฐ 404,500์ด๋๋ผ๋ resolve
๋ก ๋ฐํํ๋ฉฐ, ๋คํธ์ํฌ ์ฅ์ ๋ฐ์์์๋ง reject
๋ก ๋ฐํํ๋ค. XMLHttpRequest๋ ๊ฑฐ์ ์ฌ์ฉ๋์ง ์์ผ๋ฉฐ ๊ธฐ๋ณธ ๋ด์ฅ ํจ์์ธ fetch()
๊ฐ ์ฌ์ฉ๋๊ณ ์๋ค.
์๋์ ์์๋ ๊ธฐ๋ณธ ๋ด์ฅํจ์์ธ fetch์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ Axios ๋๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก youtube ํด๋์ค๋ฅผ ๋ง๋ค์ด App ์ปดํฌ๋ํธ์ ํ๋กญ์ผ๋ก ์ ๋ฌํ๋ ๋ฐฉ์์ผ๋ก ์์ฑํ์๋ค.
App ์ปดํฌ๋ํธ์์ url์ ๋ฐ์์ฌ ์ ์์ง๋ง, ๋ฐ์์ค๋ ๋ก์ง์ ๋ถ๋ฆฌํ์ฌ App์ ๋ฃ์ด์ค์ผ๋ก์จ(DI) ๊ธฐ๋ฅ๋จ์๋ก ๋ถ๋ฆฌ๋ ์ฝ๋์์ฑ์ด ๊ฐ๋ฅํ๋ค.
์๋ฐ์คํฌ๋ฆฝํธ์ ๋ด์ฅํจ์๋ก ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ํธ์ถ, ์์ฒญํ๋ ํจ์๋ก ๋น๋๊ธฐ์ ์ผ๋ก promise๋ก ๋ฐํํ๋ค.
src/service/youtube.js
class Youtube {
constructor(key) {
this.key = key;
this.getRequestOptions = {
method: "GET",
redirect: "follow",
};
}
//youtube Class ๋ด๋ถ์ ๋น๋๊ธฐ ๋ฉ์๋๋ฅผ ์์ฑ
//๊ฐ์ฅ ์ ๋ช
ํ ๋์์์ ๋ฐ์์ค๋ url
async mostPopular() {
const response = await fetch(
`https://www.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&maxResults=25&key=${this.key}`,
this.getRequestOptions
);
//response๋ฅผ json์ผ๋ก ๋ณํ
const result = await response.json();
return result.items;
}
//๊ฒ์ํ ๋์์์ ๋ฐ์์ค๋ url
async search(query) {
const response = await fetch(
`https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=25&q=${query}&type=video&key=${this.key}`,
this.getRequestOptions
);
const result = await response.json();
return result.items.map((item) => ({ ...item, id: item.id.videoId }));
}
}
export default Youtube;
src/index.js
//youtube ๊ฐ์ฒด ์์ฑํ์ฌ App ์ปดํฌ๋ํธ์ youtube prop์ผ๋ก ์ ๋ฌ
//App์ ์ปดํฌ๋ํธ์์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ youtube url์ ๋ฐ์์ฌ ์ ์๋ค.
const youtube = new Youtube(process.env.REACT_APP_YOUTUBE_API_KEY);
ReactDOM.render(
<React.StrictMode>
<App youtube={youtube} />
</React.StrictMode>,
document.getElementById("root")
);
API๋ฅผ ๋ถ๋ฌ์ฌ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก params ๋จ์๋ก ๋ถ๋ฆฌํ์ฌ key : value์ ํํ๋ก ์์ฑํ ์ ์์ด ์ฝ๋ ๊ฐ๋ ์ฑ์ด ์ข๋ค.
src/service/youtube.js
class Youtube {
//httpClient์ผ๋ก ๊ณตํต์ ์ผ๋ก ์ฌ์ฉ๋๋ baseUrl, key์ ๋ณด๋ฅผ ๋ฐ์์ด
constructor(httpClient) {
this.youtube = httpClient;
}
async mostPopular() {
//๋น๊ต https://www.googleapis.com/youtube/v3/videos?part=snippet&chart=mostPopular&maxResults=25&key=${this.key}
const response = await this.youtube.get("videos", {
params: {
part: "snippet",
chart: "mostPopular",
maxResults: 25,
},
});
return response.data.items;
}
async search(query) {
//๋น๊ต https://www.googleapis.com/youtube/v3/search?part=snippet&maxResults=25&q=${query}&type=video&key=${this.key}
const response = await this.youtube.get("search", {
params: {
part: "snippet",
maxResults: 25,
q: query,
type: "video",
},
});
return response.data.items.map((item) => ({
...item,
id: item.id.videoId,
}));
}
}
export default Youtube;
src/index.js
const httpClient = axios.create({
baseURL: "https://www.googleapis.com/youtube/v3",
params: { key: process.env.REACT_APP_YOUTUBE_API_KEY },
});
const youtube = new Youtube(httpClient);
ReactDOM.render(
<React.StrictMode>
<App youtube={youtube} />
</React.StrictMode>,
document.getElementById("root")
);
๋ค๋ฅธ ๊ณณ์ ์ฌ์ฉ๋ ์์์ง๋ง DI์ ๋ค๋ฅธ ์์์ฌ์ ์ฐธ๊ณ ์ผ์ ์์ฑํ์์ต๋๋ค. ์๋์ ๊ฐ์ด DI๋ฅผ ํด์ค๋, ์ธ์คํด์ค(imageUploader)๋ง prop
์ผ๋ก ๋๊ฒจ์ค ์ ์๋ ๊ฒ์ด ์๋๋ผ component์ ํํ๋ prop
์ผ๋ก ์ ๋ฌ์ด ๊ฐ๋ฅํฉ๋๋ค. <ImageFileInput />
์ด๋ผ๋ component๊ฐ ์ฌ์ฉ๋์ด์ผ ํ ๊ณณ์ ๊ธฐ๋ณธ prop๊ฐ์ผ๋ก imageUploader๋ผ๋ ํด๋์ค๋ฅผ ์ฃผ์
์ํจ <FileInput/>
์ปดํฌ๋ํธ๋ฅผ ๋ฃ์ด์ค ์ ์๋ค. ์ด๋ const FileInput = <ImageFileInput imageUploader={imageUploader} />
๋ก ์์ฑํ์ง ์๊ณ prop
๋ฅผ ๋ฐ์ ๋ฃ์ด์ฃผ๋ ๊ฒ์ ์ถํ FileInput์ ์ถ๊ฐ์ ์ผ๋ก ํ ๋น๋ prop
์ ์ ์ฉ์ด ๊ฐ๋ฅํ๋๋ก ํ์ฅ์ฑ์ ์ํด์ ์
๋๋ค. ๊ณต๋ถํ๋ ์ค์ด์ง๋ง, ์ปดํฌ๋ํธ ์์ฒด๋ prop์ผ๋ก ๋๊ฒจ์ค ์ ์๋ค๋ ๊ฒ์ ์ฒ์ ์๊ฒ๋์ ์ถ๊ฐ๋ก ๋ฃ์ด๋ณด์์ต๋๋ค.
src/index.js
const authService = new AuthService();
//ImageUploader๋ ์ด๋ฏธ์ง ํ์ผ์ ์
๋ก๋ ๊ฐ๋ฅํ API๋ฅผ ์ฐ๊ฒฐํ ํด๋์ค์
๋๋ค
const imageUploader = new ImageUploader();
//ํ์ฅ์ฑ์ ์ํด props๋ก ๋ฐ๊ณ ์ ๋ฌํจ
const FileInput = (props) => (
<ImageFileInput {...props} imageUploader={imageUploader} />
);
//component prop ์ธ๊ฒฝ์ฐ ๋ณดํต ๋๋ฌธ์๋ก ์ ๋ฌํจ
ReactDOM.render(
<React.StrictMode>
<App authService={authService} FileInput={FileInput} />
</React.StrictMode>,
document.getElementById("root")
);
๋๋ฆผ์ฝ๋ฉ ๊ฐ์ ๋ด์ฉ์ ๋ฐํ์ผ๋ก ์์ฑํ์์ต๋๋ค.
DI์ ๋ํด ์ฐธ๊ณ ํ ๊ธ
XMLHttpRequest ๊ด๋ จ ์ฐธ๊ณ ํ ๊ธ
fetch MDN