반응형
이번이 마지막 시간입니다. 앞 시간에 코드를 보면 제가 직접 용어들을 입력 해뒀습니다. 따라서 모든 용어가 존재하지 않는 문제가 발생합니다. 그 대안으로 국어사전에서 제공하는 API를 사용하여 단어를 검색 할 수 있도록 페이지를 만들었습니다.
해당 페이지에서 단어를 입력하면 국어사전에서 결과를 가져와 단어를 나열 해줍니다.
국어사전 페이지 UI 구현하기
먼저 html 구조를 작성 하겠습니다.
<div id="noteArea" class="feature-area">
<!-- 검색 헤더 영역 -->
<div class="dictionary-search-header">
<div class="dictionary-search-container">
<span class="material-icons">search</span>
<input type="text" id="dictionarySearchInput" placeholder="단어 검색...">
<button id="dictionarySearchButton" class="dictionary-search-button">
<span class="material-icons">arrow_forward</span>
</button>
</div>
</div>
<!-- 검색 결과 영역 -->
<div class="dictionary-content">
<div class="dictionary-result">
<!-- 검색 전 안내 메시지 -->
<div class="dictionary-placeholder">
<span class="material-icons">menu_book</span>
<p>검색어를 입력하시면<br>표준국어대사전의 결과가 표시됩니다.</p>
</div>
<!-- 검색 결과 표시 영역 -->
<div class="dictionary-result-content" style="display: none;">
<div class="word-header">
<h3 class="word-title">검색된 단어</h3>
<span class="word-pronunciation">[발음]</span>
</div>
<div class="word-meanings">
<div class="word-type">품사</div>
<ol class="meaning-list">
<li class="meaning-item">
<span class="meaning-text">단어의 뜻이 여기에 표시됩니다.</span>
</li>
</ol>
</div>
</div>
</div>
</div>
</div>
그 다음으로는 CSS를 사용하여 꾸며보겠습니다.
/* 검색창 컨테이너 스타일 */
.dictionary-search-container {
display: flex;
align-items: center;
padding: 8px 16px;
background: white;
border: 1px solid #dfe1e5;
border-radius: 24px;
margin: 16px;
transition: all 0.2s ease;
}
.dictionary-search-container:focus-within {
border-color: #1a73e8;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
/* 검색 아이콘 스타일 */
.dictionary-search-container .material-icons {
color: #5f6368;
margin-right: 8px;
font-size: 20px;
}
/* 검색 입력창 스타일 */
#dictionarySearchInput {
border: none;
outline: none;
width: 100%;
font-size: 14px;
color: #3c4043;
background: transparent;
margin-right: 8px;
}
#dictionarySearchInput::placeholder {
color: #80868b;
}
/* 검색 결과 영역 스타일 */
.dictionary-content {
padding: 16px;
height: calc(100% - 85px);
overflow-y: auto;
}
/* 검색 전 안내 메시지 스타일 */
.dictionary-placeholder {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 200px;
color: #5f6368;
text-align: center;
}
.dictionary-placeholder .material-icons {
font-size: 48px;
margin-bottom: 16px;
color: #1a73e8;
}
/* 검색 결과 카드 스타일 */
.dictionary-result-content {
background: white;
border-radius: 8px;
box-shadow: 0 1px 2px rgba(0,0,0,0.1);
padding: 20px;
}
/* 단어 제목 영역 스타일 */
.word-header {
margin-bottom: 16px;
}
.word-title {
font-size: 20px;
font-weight: 500;
color: #1a73e8;
margin: 0 0 4px 0;
}
.word-pronunciation {
font-size: 14px;
color: #5f6368;
}
/* 단어 의미 영역 스타일 */
.word-type {
font-size: 13px;
color: #202124;
font-weight: 500;
margin-bottom: 8px;
}
.meaning-list {
margin: 0;
padding-left: 20px;
}
.meaning-item {
font-size: 14px;
color: #3c4043;
line-height: 1.6;
margin-bottom: 8px;
}
구조는 간단합니다. 바로 다음 기능으로 가시죠!
API를 사용하여 국어사전 결과 불러오기
js/ config.js 파일 생성
해당 파일에는 국어사전에서 제공받은 API 키를 입력 할 것입니다. 하루 제한 50,000건 이고 추가 금액은 없으니 안심입니다.
// 하루 50,000번 제한 있음 -> 더 사용 한다고 추가 금 안 나온다. 따라서 이거 봐도 사용은 자유롭게 해도 상관 없음
// 사용자도 없을 것 같긴 하지만 뭐 어때
export const CONFIG = {
DICTIONARY_API_KEY: '제공 받은 키 입력',
DICTIONARY_API_URL: 'https://stdict.korean.go.kr/api/search.do'
};
js/dictionaryManager.js 파일 생성
해당 파일에는 국어사전 API를 가져와 원하는 단어를 검색창에 입력하여 결과를 가져와 띄우는 작업을 합니다.
import { CONFIG } from './config.js';
class DictionaryManager {
constructor() {
// DOM 요소 초기화
this.searchInput = document.getElementById('dictionarySearchInput');
this.searchButton = document.getElementById('dictionarySearchButton');
this.resultContainer = document.querySelector('.dictionary-result');
this.placeholder = document.querySelector('.dictionary-placeholder');
this.resultContent = document.querySelector('.dictionary-result-content');
this.initializeEventListeners();
}
// 이벤트 리스너 설정
initializeEventListeners() {
// 검색 버튼 클릭 시 검색 실행
this.searchButton.addEventListener('click', () => this.handleSearch());
// Enter 키 입력 시 검색 실행
this.searchInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
this.handleSearch();
}
});
}
// 검색 처리
async handleSearch() {
const searchTerm = this.searchInput.value.trim();
if (!searchTerm) return;
try {
this.showLoading();
const result = await this.searchDictionary(searchTerm);
this.displayResult(result);
} catch (error) {
this.showError(error.message);
}
}
// API 호출
async searchDictionary(query) {
const params = new URLSearchParams({
key: CONFIG.DICTIONARY_API_KEY,
q: query,
req_type: 'json',
type1: 'word',
pos: 1
});
try {
const response = await fetch(`${CONFIG.DICTIONARY_API_URL}?${params}`);
if (!response.ok) {
throw new Error('API 요청에 실패했습니다.');
}
const data = await response.json();
return this.parseApiResponse(data);
} catch (error) {
throw new Error('검색 중 오류가 발생했습니다.');
}
}
// API 응답 데이터 파싱
parseApiResponse(data) {
if (!data.channel || !data.channel.item) {
throw new Error('검색 결과가 없습니다.');
}
return data.channel.item.map(item => ({
word: item.word,
pronunciation: item.pronunciation || '',
pos: item.pos || '',
definition: item.sense.definition.replace(/^\d+\.\s*/, '')
}));
}
// 검색 결과 화면 표시
displayResult(results) {
this.placeholder.style.display = 'none';
this.resultContent.style.display = 'block';
const firstResult = results[0];
this.resultContent.innerHTML = `
<div class="word-header">
<h3 class="word-title">${firstResult.word}</h3>
${firstResult.pronunciation ?
`<span class="word-pronunciation">[${firstResult.pronunciation}]</span>` : ''}
</div>
<div class="word-meanings">
${firstResult.pos ?
`<div class="word-type">${firstResult.pos}</div>` : ''}
<ol class="meaning-list">
${results.map(result => `
<li class="meaning-item">
<span class="meaning-text">${result.definition}</span>
</li>
`).join('')}
</ol>
</div>
`;
}
// 로딩 상태 표시
showLoading() {
this.resultContent.style.display = 'none';
this.placeholder.innerHTML = `
<span class="material-icons loading">sync</span>
<p>검색 중입니다...</p>
`;
this.placeholder.style.display = 'flex';
}
// 에러 메시지 표시
showError(message) {
this.resultContent.style.display = 'none';
this.placeholder.innerHTML = `
<span class="material-icons">error_outline</span>
<p>${message}</p>
`;
this.placeholder.style.display = 'flex';
}
}
// 인스턴스 생성
const dictionaryManager = new DictionaryManager();
제공하는 예제 자료를 활용 한 것입니다. 복잡해 보이긴 합니다만 아직 코딩 능력이 부족해 양해 부탁드립니다.
결과는 가장 처음 사진과 같이 잘뜹니다! 이제 저희는 드디어 끝났습니다~
하루 1개씩 올릴려고 했는 데, 흠.. 죄송합니다 그게 쉽지는 않네요. 현재 크롬 확장 스토어에 저의 프로그램이 올라가있습니다.
많은 관심 부탁드리고, 언제나 피드백은 환영입니다. 감사합니다.
반응형
'개발하기 > Google Extension' 카테고리의 다른 글
[EP.04] pdf 파일을 불러와 용어를 인식 후 뜻 풀이하기 (0) | 2025.01.16 |
---|---|
[EP.03] 비즈니스 용어를 정리하고 해당 페이지의 UI를 구현하기 (1) | 2024.12.19 |
[EP.02] 확장자 프로그램 기획하기: 비즈니스 용어 도우미 (1) | 2024.12.18 |
[Ep.01]Google 확장자 업무 용어 프로그램 만들기 (+간단한 맛보기) (0) | 2024.12.17 |