์๋ผ๋API๋ฅผ ์ฌ์ฉํด์ ์ฑ ๊ฒ์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ ค๊ณ ํ๋ค.
๋์ค์ ๊ธฐ์ตํ ์ ์๋๋ก
๊ณผ์ ์ ๊ธฐ๋กํ๊ธฐ ์ํด ํฌ์คํ ์์ฑํจ
์์ฒญํด์ผํ ์ฟผ๋ฆฌ์คํธ๋ง์ ์๋์ ๊ฐ์
์๋ผ๋ Open API ๋งค๋ด์ผ
1. ์์ฒญ (Request) 1) ์ํ ๊ฒ์ API 2) ์ํ ๋ฆฌ์คํธ API 3) ์ํ ์กฐํ API 4) ์ค๊ณ ์ํ ๋ณด์ ๋งค์ฅ ๊ฒ์ API 2. ์๋ต (Response) 1) ์ํ ๊ฒ์/์ํ ๋ฆฌ์คํธ/์ํ ์กฐํ API 2) ์ํ ์กฐํ API : ๋ถ๊ฐ์ ๋ณด 3) ์ค๊ณ ์ํ ๋ณด
docs.google.com
| ์์ฒญ URL์ํ : http://www.aladin.co.kr/ttb/api/ItemSearch.aspx?ttbkey=[TTBKey]&Query=aladdin&QueryType=Title&MaxResults=10&start=1&SearchTarget=Book&output=xml&Version=20131101 |

postman์ผ๋ก ํ ์คํธ๋ฅผ ํด๋ดค๋ค.
์ ๋จ.

๊ฒ์์ฐฝ ์ปดํฌ๋ํธ์ css ์์ฑํด์ ๊ฒ์์ฐฝ ํ ๋ง๋ฌ (๊ณ์ ์์ ํ ๊ฑฐ๋ผ์ ๋๊ฐ๋ง๋ฌ)
React icon ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์นํด์ ์ฌ์ฉ
https://react-icons.github.io/react-icons/search/#q=search
React icons search results
react-icons.github.io
import React from "react";
import "./SearchBar.css";
import { FaSearch } from "react-icons/fa";
const Searchbar = () => {
return (
<>
<div className="searchSection">
<form>
<label htmlFor="">
<input
type="text"
className="search"
placeholder="๊ฒ์์ด๋ฅผ ์
๋ ฅํ์ธ์."
/>
<a href="" className="searchBtn">
<FaSearch />
</a>
</label>
</form>
</div>
</>
);
};
export default Searchbar;
.searchSection {
border: 1px solid #527853;
margin: 150px 0 50px 0;
display: flex;
box-shadow: 5px 5px 5px #f5f5f5;
}
.search {
padding-left: 30px;
width: 400px;
height: 50px;
border: none;
}
.searchBtn {
padding: 20px;
width: 100px;
height: 50px;
color: #527853;
}

๊ทธ๋ฆฌ๊ณ ์ผ๋จ ๋ด๊ฐ ๊ตฌํํ๊ณ ์ ํ๋ ๊ธฐ๋ฅ์
1. ๊ฒ์์ด ์ ๋ ฅ ํ ๊ฒ์ ๋ฒํผ ๋๋ฅด๋ฉด ๊ฒ์ํ์ด์ง(Search) ๋ก ๋์ด๊ฐ๋ค.
๊ทธ๋ฆฌ๊ณ ๊ทธ ํ์ด์ง์์ ํ๋ผ๋ฏธํฐ๋ก ๊ฒ์์ด๋ฅผ ๋ฐ์์ ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ ํ๋ฉด
2. ๊ฒ์์ด๋ฅผ ์ ๋ ฅํ ๊ฒฝ์ฐ ์ค์๊ฐ์ผ๋ก ๊ฒ์ํด์ ์๋์ ์๊ฒ ๋ณด์ฌ์ฃผ๋?
์๋์ ๊ฐ์ ๊ธฐ๋ฅ๋ ์ถ๊ฐํด ๋ณด๊ณ ์ถ๋ค.

์ผ๋จ 1๋ฒ ๊ธฐ๋ฅ์ ๊ตฌํํด๋ณด๊ฒ ๋ค.
Searchbar์์ ์ผ๋จ ๊ฒ์์ด๋ฅผ ์ ์ฅํด์ ๋ค์ ํ์ด์ง๋ก ๋๊ฒจ ์ค ์ ์๋๋ก
form์๋ submit ์ ๋ฐ์ํ๋ handleSubmit ํจ์๋ฅผ ์ถ๊ฐํ๊ณ ,
input์๋ ๊ฒ์์ด๋ฅผ ํ ๊ธ์ ์ ๋ ฅํ ๋๋ง๋ค ์ ์ฅํ๋๋ก handleChange ํจ์๋ฅผ ์ถ๊ฐํ์ฌ ๊ฐ์ ์ ์ฅํ๋ค.
<div className="searchSection">
<form onSubmit={handleSubmit}>
<label>
<input
onChange={handleChange}
value={searchValue}
type="text"
className="search"
placeholder="๊ฒ์์ด๋ฅผ ์
๋ ฅํ์ธ์."
/>
<button type="submit" className="searchBtn">
<FaSearch />
</button>
</label>
</form>
</div>
์ผ๋จ 1๋ฒ ๊ธฐ๋ฅ์๋ handleChange ํจ์๋ ์ฌ์ฉ๋์ง ์์ ๋ฏ ํด์ ์ผ๋จ ํ๋ง ์ก์์ค๋ค.
๊ทธ๋ฆฌ๊ณ useNavigate๋ฅผ ์ฌ์ฉํด์
๊ฒ์์ด๋ฅผ ์ ๋ ฅํ๊ณ submit์ํ๋ฉด ์ ์ฅ๋ searchValue๋ฅผ ๊ฐ์ง๊ณ searchํ์ด์ง๋ก ์ด๋ํ๊ฒํ๋ค.
const [searchValue, setSearchValue] = useState("");
const navigate = useNavigate();
//submit ์
const handleSubmit = (e) => {
e.preventDefault();
if (searchValue === "") {
alert("๋ด์ฉ์ ์
๋ ฅํด ์ฃผ์ธ์!");
} else {
setSearchValue(e.target.value);
navigate(`/search?q=${searchValue}`); //q= ๊ฒ์์ด๋ก ์์ฒญํ๋ค.
setSearchValue("");
}
};
//๊ฒ์์ด ์
๋ ฅ ์
const handleChange = (e) => {
setSearchValue(e.target.value);
// console.log(searchValue);
};
Searchํ์ด์ง๋ก ์ด๋ํ์ ๊ฒฝ์ฐ ํ๋ผ๋ฏธํฐ๋ก ใ ใ ใ ใ ๊ฐ ๋์ด์จ๋ค

๊ทธ๋ฌ๋ฉด ์ด์ ํด์ผํ ์ผ์
๋ฐ์ ๊ฒ์์ด๋ฅผ ๊ฐ์ง๊ณ
api๋ก ์๋ผ๋์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํ๋ ๊ฒ๋ง ๋จ์
const Search = () => {
//๊ฒ์์ด๋ก ๋์ด์ค๋ ํ๋ผ๋ฏธํฐ ๊ฐ์ ธ์ค๊ธฐ
const queryString = useLocation().search;
const queryParams = new URLSearchParams(queryString);
const query = queryParams.get("q"); // q์ ํด๋นํ๋ ๊ฐ์ ์ฟผ๋ฆฌ์คํธ๋ง์์ ๊ฐ์ ธ์ด
console.log(query);
์์ ์ฝ๋๋ฅผ ์ฌ์ฉํด์ q์ ํ๋ผ๋ฏธํฐ์ ๊ฐ์ ๊ฐ์ ธ์์
ํ ์คํธ๋ก ์ฝ์์ ์ถ๋ ฅํ๋ค.

์ ์ถ๋ ฅ๋๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
์ด์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์์ ์ถ๋ ฅ๋ง ํ๋ฉด๋จ.
resultBooks usestate๋ฅผ ๋ง๋ค์ด์
๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋ด๋๋ก ํ๊ฒ ๋ค.
์ผ๋จ ํ์ด์ง๊ฐ ์์ํ๋ฉด fetchBooks() ๋ฅผ ์คํํ๋ค.
fetchBooks๋ ์๋ผ๋์ ํ๋ผ๋ฏธํฐ๋ก ๋์ด์จ query๋ก ๊ฒ์ํด์
๊ทธ๊ฒฐ๊ณผ๋ฅผ setResultBooks๋ก ๊ฒฐ๊ณผ ๋ฐฐ์ด์ ์ ์ฅํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ถ๋ ฅ ์ map ๋ฐ๋ณต๋ฌธ์ผ๋ก ๊ทธ ๊ฒฐ๊ณผ๊ฐ์ ์ถ๋ ฅํ๋ค.
const Search = () => {
//๊ฒ์์ด๋ก ๋์ด์ค๋ ํ๋ผ๋ฏธํฐ ๊ฐ์ ธ์ค๊ธฐ
const queryString = useLocation().search;
const queryParams = new URLSearchParams(queryString);
const query = queryParams.get("q"); // q์ ํด๋นํ๋ ๊ฐ์ ์ฟผ๋ฆฌ์คํธ๋ง์์ ๊ฐ์ ธ์ด
const [resultBooks, setResultBooks] = useState([]);
useEffect(() => {
fetchBooks();
}, []);
const fetchBooks = async () => {
const response = await fetch(
`http://www.aladin.co.kr/ttb/api/ItemSearch.aspx?ttbkey=${
import.meta.env.VITE_BOOK_API
}&Query=${query}&QueryType=Title&MaxResults=10&start=1&SearchTarget=Book&Cover=Big&output=js&Version=20131101`
);
const data = await response.json();
setResultBooks(data.item);
};
return (
<>
{resultBooks.map((book) => (
<BookCard key={book.itemId} book={book} />
))}
</>
);
};
์๋ผ๋์ ๊ฒ์ํด๋ดค๋ค.
์๋ผ๋์ ๊ฐ์ข ์ํ๊ณผ ๋์๊ฐ ๋์จ๋ค.
css์ ์ฟผ๋ฆฌ์คํธ๋ง์ ํ ๋ฒ ๋ค์ ์์ ์ ํด์ผํ ๋ฏ
