실습 내용
해설 강의를 들으면서 컴포넌트화 및 동작 구조에 대해 파악.
실습 과정(주요 내용 요약)
0. 라이브러리 사용x, 바닐라 스크립트만을 이용한다.
- 리액트 사용전 바닐라로 컴포넌트,상태관리,API 호출 등 베이스가 되는 것을 먼저 배워 개념을 익히는것 같다.)
1. 화면 구성 요소는 컴포넌트로 만들어 구조화 한다.
동작구조
1-1. index.html(main.js 불러오기)
1-2. main.js(App.js 불러오기)
1-3. App.js(애플리케이션의 메인 컨트롤러 역할을 하며, 다양한 컴포넌트들을 불러오며 초기화 및 관리 한다.,$target 매개 변수를 주어 페이지의 어느 부분에 렌더링 될지를 지정한다. 그 외 api 호출 및 상태 관리라던가 로컬스토리지등 중요한 기능은 App에 몰아 넣었다.)
1-3-1. 컴포넌트들
- Loading: 로딩 상태를 표시하는 컴포넌트
- DarkModeToggle: 다크 모드 전환 기능의 컴포넌트
- SearchInput: 검색 기능을 제공합니다. 검색과 랜덤 검색 두 가지 모드 제공
- Banner: 애플리케이션 상단에 배너를 표시하는 컴포넌트
- SearchResult: 검색 결과를 보여주며, 특정 항목 클릭시 상세 정보를 보여주는 기능을 연결
- ImageInfo: 선택된 이미지의 상세 정보를 표시
1-4. Searchinput.js(App.js에서 불러온 컴포넌트중 일부 이며 비슷한 형식으로 여러 컴포넌트를 만들어 App.js에 설정 해주면 된다.)
2. 각 컴포넌트는 각각의 상태 값을 가지고 있고, render 함수를 통해 현제 상태를 랜더링 한다.
2-1. Searchinput.js 검색기능 컴포넌트 코드 👇
class SearchInput {
constructor({ $target, onSearch,onRandomSearch}) {
const $wrapper = document.createElement('section');
$wrapper.className = 'SerchInputSection';
$target.appendChild($wrapper);
//입력
const $searchInput = document.createElement("input");
this.$searchInput = $searchInput;
this.$searchInput.placeholder = "고양이를 검색해보세요.|";
$searchInput.className = "SearchInput";
$wrapper.appendChild($searchInput)
$searchInput.addEventListener("keypress", e => {
if (e.key === 'Enter') {
onSearch(e.target.value,this.$limitCount.value);
// 최근 키워드 저장
this.KeywordHistory.addKeyword(e.target.value)
}
});
//셀렉트 ui
const $limitCount = document.createElement('select');
this.$limitCount = $limitCount;
this.$limitCount.classlist = 'LimitCount'
const LimitCountOptions = [10,25,50]
LimitCountOptions.map((option) => {
let $option = document.createElement('option');
$option.value = option;
$option.textContent = `${option}개`;
$limitCount.appendChild($option)
})
$wrapper.appendChild($limitCount)
//랜덤
const $randomButton = document.createElement("button");
this.$randomButton = $randomButton;
this.$randomButton.className = 'RandomButton';
this.$randomButton.textContent = '랜덤고양이';
$wrapper.appendChild($randomButton);
$randomButton.addEventListener("click", e => {
onRandomSearch();
});
this.KeywordHistory = new KeywordHistory({
$target : $wrapper,
onSearch
})
}
render() {}
}
export default SearchInput
위의 SearchInput 클래스는 웹 애플리케이션의 검색 기능을 관리하는 자바스크립트 컴포넌트입니다. 이 클래스는 사용자 인터페이스를 구성하고, 검색 관련 이벤트를 처리합니다. 주요 구성 요소와 기능은 다음과 같습니다:
- 컴포넌트 초기화:
- $target 파라미터로 받은 요소에 검색 입력 섹션을 추가합니다. 이는 검색 인풋과 선택적으로 검색 결과 수를 제한하는 드롭다운, 그리고 랜덤 검색 버튼이 포함된 섹션입니다.
- 검색 입력 필드:
- 텍스트 입력 필드를 생성하고, 사용자가 엔터 키를 누를 때 onSearch 콜백 함수를 트리거합니다. 이 함수는 입력된 값을 인수로 받아 검색을 실행합니다.
- 입력 필드는 사용자가 검색어를 입력할 때마다 "최근 키워드" 기록에 해당 검색어를 저장합니다.
- 결과 수 제한 선택기:
- 드롭다운 메뉴를 생성하여 사용자가 검색 결과의 수를 선택할 수 있게 합니다. 옵션은 10개, 25개, 50개로 구성됩니다.
- 랜덤 검색 버튼:
- 사용자가 랜덤 검색 버튼을 클릭하면 onRandomSearch 콜백 함수가 실행되어 무작위 고양이 이미지를 검색합니다.
- 키워드 히스토리:
- KeywordHistory 인스턴스를 생성하여 사용자의 검색 키워드 히스토리를 관리하고, 이를 UI에 표시합니다. 이 컴포넌트는 사용자의 이전 검색을 저장하고, 선택적으로 이전 검색을 재실행할 수 있는 기능을 제공합니다.
2-2. KeywordHistory.js 검색 키워드 이력 관리 컴포넌트👇
import uniqueArray from './utils/uniqueArray.js';
class KeywordHistory {
$keywordHistory = null;
data = null;
constructor({ $target,onSearch }) {
const $keywordHistory = document.createElement('ul');
this.$keywordHistory = $keywordHistory;
this.$keywordHistory.className = 'KeywordHistory'
$target.appendChild(this.$keywordHistory)
// this.data = [
// '아',
// '고양이',
// 'cat'
// ]
this.onSearch = onSearch;
this.init()
this.render()
}
init(){
const data = this.getHistory();
this.setState(data);
}
addKeyword(keyword) {
let keywordHistory = this.getHistory();
keywordHistory.unshift(keyword);
// 중복제거
keywordHistory = uniqueArray(keywordHistory)
keywordHistory = keywordHistory.slice(0,5)
localStorage.setItem('keywordHistory',keywordHistory.join(','))
this.init();
}
getHistory(){
return localStorage.getItem('keywordHistory')
=== null ? [] :localStorage.getItem('keywordHistory').split(',');
}
setState(nextData) {
this.data = nextData;
this.render();
}
bindEvent(){
this.$keywordHistory.querySelectorAll('li button').forEach(
($item,index) => {
$item.addEventListener('click', () =>{
console.log(this.data[index])
this.onSearch(this.data[index])
//인풋상자에 서치된 키워드 넣기
document.querySelector('.SearchInput').value = this.data[index]
})
});
}
render() {
this.$keywordHistory.innerHTML = this.data
.map(
keyword => `
<li><button>${keyword}</button></li>
`
).join('');
this.bindEvent();
}
}
export default KeywordHistory
위의 KeywordHistory 클래스는 웹 애플리케이션에서 사용자의 검색 키워드 이력을 관리하는 컴포넌트입니다. 이 클래스는 사용자의 이전 검색 키워드를 로컬 스토리지에 저장하고, 이를 UI에 표시하여 사용자가 이전에 검색했던 키워드를 쉽게 재사용할 수 있도록 합니다. 주요 구성 요소와 기능은 다음과 같습니다:
- 초기화 및 DOM 조작:
- 컴포넌트는 <ul> 요소를 생성하여 $target 내에 추가합니다. 이 요소는 검색 키워드의 목록을 표시하는 데 사용됩니다.
- 검색 키워드 관리:
- addKeyword 메소드를 통해 새로운 검색 키워드를 추가하며, 중복을 제거하고 최근 5개 키워드만을 유지합니다. 이 과정은 uniqueArray 함수를 사용하여 처리합니다.
- 로컬 스토리지 사용:
- getHistory 메소드를 통해 로컬 스토리지에서 검색 키워드 이력을 가져옵니다. 만약 로컬 스토리지에 데이터가 없으면 빈 배열을 반환합니다.
- ✔ **상태 관리 및 렌더링:**
- setState 메소드를 통해 내부 데이터를 업데이트하고 render 메소드를 호출하여 UI를 갱신합니다. 렌더링 과정에서는 저장된 키워드를 버튼으로 만들어 리스트 형태로 표시합니다.
- 이벤트 바인딩:
- bindEvent 메소드는 각 키워드 버튼에 이벤트 리스너를 연결합니다. 사용자가 버튼을 클릭하면 해당 키워드로 검색을 실행하고, 검색 입력 필드에 해당 키워드를 채웁니다.
SearchInput , KeywordHistory 클래스는 HTML 요소를 동적으로 생성하고, 이벤트 리스너를 통해 사용자 상호작용을 처리하는 전형적인 바닐라 자바스크립트 컴포넌트의 예입니다(GPT 답변)
3. api fetch 코드를 async,await 문을 이용하여 적절하게 비동기 처리 하며 응답 에러도 대비해야 한다.
import config from './config.js'
const { API_ENDPOINT, REQUEST_ERROR } = config;
const request = async (url) => {
try {
const result = await fetch(url);
if (result.status === 200){
return result.json()
} else {
throw REQUEST_ERROR[result.status]
}
} catch (error){
alert(error.msg)
return { data: null }
}
}
const api = {
fetchCats: keyword => {
return request(`${API_ENDPOINT}/api/cats/search?q=${keyword}`)
},
fetchCatsWithLimit: (keyword,limit) => {
return request(`${API_ENDPOINT}/api/cats/search?q=${keyword}&limiy=${limit}`)
},
fetchCatsPage: (keyword,page) => {
return request(`${API_ENDPOINT}/api/cats/search?q=${keyword}&page=${page}`)
},
fetchRandomCats: () => {
return request(`${API_ENDPOINT}/api/cats/random50`)
},
fetchCatDetail: id => {
return request(`${API_ENDPOINT}/api/cats/${id}`)
},
};
export default api
위의 코드는 API 요청을 처리하는 JavaScript 유틸리티를 정의하는 모듈입니다. 이 모듈은 고양이 관련 데이터를 요청하는 데 특화된 함수들을 포함하고 있습니다. 주요 구성 요소와 기능은 다음과 같습니다:
- 컨피그레이션 가져오기:
- config.js 파일에서 API 엔드포인트(API_ENDPOINT)와 요청 에러 메시지(REQUEST_ERROR)를 가져옵니다. 이 값들은 API 요청을 처리할 때 사용됩니다.
- request 함수:
- 비동기 함수로, fetch를 사용하여 주어진 URL에 대한 HTTP 요청을 실행합니다.
- 응답 상태가 200일 경우, JSON 형식으로 응답 데이터를 반환합니다.
- 그 외의 상태 코드일 경우, REQUEST_ERROR에서 해당 상태 코드에 대응하는 오류 메시지를 예외로 발생시킵니다.
- 요청이 실패하거나 예외가 발생하면, 사용자에게 경고를 표시하고, 데이터를 null로 설정한 객체를 반환합니다.
- API 메서드:
- fetchCats: 주어진 키워드로 고양이를 검색
- fetchCatsWithLimit: 검색 결과의 수를 제한하여 고양이를 검색
- fetchCatsPage: 페이징 처리된 검색 결과를 요청
- fetchRandomCats: 랜덤하게 50마리의 고양이 데이터 조회
- fetchCatDetail: 특정 고양이의 상세 정보를 조회
- 모듈 내보내기:
- 정의된 api 객체를 모듈의 기본값으로 내보냅니다. 이 객체는 애플리케이션의 다른 부분에서 API 요청 기능을 사용할 수 있게 해줍니다.
동작 영상
작업 코드
https://github.com/josungman/Programmer-s_Web_App_Dev_Course/tree/main/week7/part10
Programmer-s_Web_App_Dev_Course/week7/part10 at main · josungman/Programmer-s_Web_App_Dev_Course
클라우딩 어플리케이션 엔지니어링 코스. Contribute to josungman/Programmer-s_Web_App_Dev_Course development by creating an account on GitHub.
github.com
느낀점
고양이 사이트 만드는 문제가 2개 (1회차,개선버전) 로 분리 되어 있었으며 개선버전 의 코드 이다.
컴포넌트와,구조가 어떻게 이루어져있는지 알 수 있었다.
바닐라 스크립트로만 진행 하였지만 추후 리액트도 비슷한 구조로 이루저져있지 않을까 싶어
중요하다고 생각되는 부분만 정리해 보았다.
'클라우딩 어플리케이션 엔지니어링 TIL > 7주차' 카테고리의 다른 글
[파트03] javascript 실습(고양이 사진 검색 사이트) (0) | 2024.05.28 |
---|