이번 포스팅에서는 노벨상 탐색기 프로젝트의 핵심 기능 중 하나인 검색창과 관련된 코드를 리뷰합니다. 검색창은 사용자로부터 입력을 받아 API를 호출하고, 결과를 필터링하여 사용자에게 표시하는 중요한 UI/UX 요소입니다. 리뷰 대상은 다음과 같습니다:
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import "./SearchBox.css";
function SearchBox({ onSearch }) {
const [query, setQuery] = useState("");
const [year, setYear] = useState("");
const [prizeCategory, setPrizeCategory] = useState("");
const navigate = useNavigate();
const handleSubmit = async (e) => {
e.preventDefault();
try {
let apiUrl = `https://api.nobelprize.org/2.1/laureates?`;
if (query) apiUrl += `name=${query}&`;
if (year) apiUrl += `nobelPrizeYear=${year}&`;
if (prizeCategory) apiUrl += `nobelPrizeCategory=${prizeCategory}`;
const response = await fetch(apiUrl);
const data = await response.json();
const filteredData = data.laureates.filter((laureate) =>
laureate.fullName.en.toLowerCase().startsWith(query.toLowerCase())
);
onSearch(filteredData || []);
navigate("/search-results");
} catch (error) {
console.error("Error fetching data:", error);
}
};
return (
<div className="search-container">
<form onSubmit={handleSubmit}>
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="이름 검색"
/>
<input
type="text"
value={year}
onChange={(e) => setYear(e.target.value)}
placeholder="수상 연도"
/>
<input
type="text"
value={prizeCategory}
onChange={(e) => setPrizeCategory(e.target.value)}
placeholder="수상 종류"
/>
<button type="submit">검색</button>
</form>
</div>
);
}
export default SearchBox;
구조적 완성도
useState를 활용해 검색 필드의 상태를 관리하며, 입력값에 실시간으로 반응합니다.useNavigate를 사용해 검색 결과 페이지로 이동을 구현한 점이 효율적입니다.API 호출 및 데이터 처리
try-catch 블록을 사용해 에러를 처리하고 있어 안정성이 돋보입니다.코드 개선 제안
setQuery("");
setYear("");
setPrizeCategory("");.search-container {
width: 100%;
max-width: 800px;
margin: 50px auto;
padding: 20px;
background-color: #f9f9f9;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
form {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
gap: 20px;
}
input {
width: 30%;
padding: 12px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 1rem;
box-sizing: border-box;
}
input:focus {
border-color: #007bff;
outline: none;
box-shadow: 0 0 5px rgba(0, 123, 255, 0.5);
}
button {
width: 20%;
padding: 12px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
font-size: 1.1rem;
cursor: pointer;
transition: background-color 0.3s ease;
}
button:hover {
background-color: #0056b3;
}
레이아웃 및 스타일링
flexbox를 사용하여 각 필드를 깔끔하게 정렬하고 간격을 유지하였습니다.box-shadow와 border-radius로 검색창에 부드러운 느낌을 더했습니다.디자인 개선 제안
@media (max-width: 768px) {
input, button {
width: 100%;
margin-bottom: 10px;
}
}import React from "react";
import "./SearchResults.css";
function SearchResults({ searchResults }) {
if (!searchResults || searchResults.length === 0) {
return <div>검색 결과가 없습니다.</div>;
}
return (
<div className="search-results">
<h2>검색 결과</h2>
<ul>
{searchResults.map((result, index) => (
<li key={index}>
<h3>{result.knownName?.en || result.fullName?.en || "이름 없음"}</h3>
<p>수상 연도: {result.nobelPrizes[0]?.awardYear}</p>
<p>수상 종류: {result.nobelPrizes[0]?.category?.en}</p>
</li>
))}
</ul>
</div>
);
}
export default SearchResults;
구조적 간결성
코드 개선 제안
const [isLoading, setIsLoading] = useState(false);.search-results {
margin: 20px;
padding: 20px;
background-color: #f9f9f9;
border: 1px solid #ddd;
border-radius: 8px;
}
.search-results h2 {
font-size: 24px;
margin-bottom: 16px;
}
.search-results li {
padding: 15px;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 6px;
margin-bottom: 16px;
}

이 코드는 검색창 구현과 관련된 구조적 완성도와 디자인의 균형이 돋보입니다. 다만, 추가적인 UX 개선 사항(로딩 상태, 에러 처리 등)을 반영하면 더 나은 사용자 경험을 제공할 수 있습니다.