오늘부터 일주일 동안 프로그래머스의 프론트엔드 채용 과제였던 '고양이 사진 검색 사이트' 해설 강의가 진행된다
이번 강의를 통해서 바닐라 자바스크립트만을 이용해서 새로운 기능을 구현해 과제의 요구사항을 충족시켜보면서 프론트엔드 개발 역량을 기를 수 있을 것이라 생각한다
과제 해설 강의를 들으며 중요한 내용, 에러 발생, 어려운 부분 등을 기록해두려고 한다
이번주도 화이팅!
# 미션 1
# 반응형 웹
유저가 사용하는 디바이스의 가로 길이에 따라 검색 결과의 row 당 column 갯수 변경
992 px 이하 : 3개
768px 이하 : 2개
576px 이하 : 1개
가로 길이가 768px 이하인 경우, 모달의 가로 길이를 디바이스 가로 길이만큼 늘리기
미디어 쿼리 사용
@media screen and (max-width: 992px) {
.SearchResult {
grid-template-columns: repeat(3, minmax(250px, 1fr));
}
}
@media screen and (max-width: 768px) {
.SearchResult {
grid-template-columns: repeat(2, minmax(250px, 1fr));
}
.ImageInfo .content-wrapper {
width: 100%;
}
}
@media screen and (max-width: 576px) {
.SearchResult {
grid-template-columns: repeat(1, minmax(250px, 1fr));
}
}
# 다크모드
/*dark mode*/
@media (prefers-color-scheme: dark) {
body {
background-color: #000;
color: white;
}
}
# 다크모드 토글
하나의 컴포넌트처럼 분리하기
DarkModeToggle 파일을 생성한 후 index.html 과 App.js 에서 등록
class DarkModeToggle {
//초기화
isDarkMode = null;
constructor({ $target, onSearch }) {
const $DarkModeToggle = document.createElement("input");
this.$DarkModeToggle = $DarkModeToggle;
this.$DarkModeToggle.type = "checkbox";
$DarkModeToggle.className = "DarkModeToggle";
$target.appendChild($DarkModeToggle);
$DarkModeToggle.addEventListener("change", (e) => {
this.setColorMode(e.target.checked);
});
this.initColorMode();
}
//초기화가 굉장히 중요하다!!!!!
initColorMode() {
//초기화 과정
//isDarkMode, checkbox html attr 상태
//matchMedia 사용해서 감지
// 미디어 쿼리를 통해서 현재 다크모드인지 아닌지 상태를 받아옴
this.isDarkMode = window.matchMedia("(prefers-color-scheme: dark)").matches;
//다크모드인지 아닌지 체크
this.$DarkModeToggle.checked = this.isDarkMode;
this.setColorMode(this.isDarkMode);
}
setColorMode(isDarkMode) {
document.documentElement.setAttribute(
"color-mode",
isDarkMode ? "dark" : "light"
);
}
}
/* 다크모드 토글 CSS */
:root[color-mode="dark"] {
--background: #000;
--textColor: white;
}
/* 적용 */
body {
background-color: var(--background);
color: var(--textColor);
}
# 시맨틱 마크업이 왜 중요한가?
시맨틱 마크업은 웹 페이지의 구조와 의미를 명확하게 표현하기 위해 HTML 태그를 적절하게 사용하는 것을 말한다
시맨틱 마크업은 중요한데 그 이유는 다음과 같다
1. 검색 엔진 최적화
2. 웹 접근성
3. 유지보수 용이성
4. 다양한 디바이스 및 브라우저 호환성
등등
# 미션 2
# 로딩 UI
UI 동작 구현 순서
1. UI 흐름 나열 = 시나리오
2. 동작이 필요한 point 뽑아내기
- browser event
- 특정 시점
3. 메소드 일단 만들어서 배치해보기
- console.log() 를 통한 인자 확인
- 동작 작성
4. 작은 리팩토링
- 중복 제거
- 변수명 점검
5. 확인 & 개선
완성된 로딩 화면
Loading.js
class Loading {
$loading = null;
data = null;
constructor({ $target }) {
const $loading = document.createElement("div");
this.$loading = $loading;
$target.appendChild(this.$loading);
this.data = {
show: false,
};
this.render();
}
show() {
this.setState({
show: true,
});
}
hide() {
this.setState({
show: false,
});
}
setState(nextData) {
this.data = nextData;
this.render();
}
render() {
if (this.data.show) {
this.$loading.innerHTML = `
<div class="Loading">
<p>
❤️🔥로딩중❤️🔥
</p>
</div>`;
} else {
this.$loading.innerHTML = ``;
}
}
}
CSS
.Loading {
position: fixed;
z-index: 10;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: rgba(0, 0, 0, 0.3);
text-align: center;
}
.Loading p {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 40px;
}
# 랜덤버튼
검색창 옆에 랜덤버튼이 위치할 수 있도록 따로 컴포넌트로 분리하지 않고 SearchInput 파일에서 작성하였다
const $randomButton = document.createElement("button");
this.$randomButton = $randomButton;
this.$randomButton.className = "RandomButton";
this.$randomButton.textContent = "랜덤고양이";
$wrapper.appendChild($randomButton);
$randomButton.addEventListener("click", (e) => {
onRandomSearch();
});
App.js 의 serchInput 에 랜덤버튼을 작동시키는 메소드 작성해주기
this.searchInput = new SearchInput({
$target,
onSearch: (keyword) => {
this.Loading.show();
api.fetchCats(keyword).then(({ data }) => {
this.setState(data);
this.Loading.hide();
});
},
onRandomSearch: () => {
console.log("랜덤?");
api.fetchRandomCats().then(({ data }) => {
this.setState(data);
this.Loading.hide();
});
},
});
api.js 에서 랜덤 버튼을 작동시킬 수 있는 api를 작성해주자
CSS는 원하는 대로 꾸미면 되지만 input창 옆에 뜨도록 설정했다
# 에러 해결 기록
# JS, CSS 파일 수정이 바로 반영 안 됨
JS 나 CSS 코드를 수정하면 서버에 바로 반영이 되지 않았다
내가 사용하는 브라우저는 구글인데 설정에서 검색 기록 및 캐시를 삭제하니 처음에는 변경이 되었다
근데 모든 사이트에서 로그아웃이 되어서 너무 불편했다...
그래서 찾은 다음 방법
package.json의 스크립트를 수정하는 것
"scripts": {
"test": "jest --config=jest.config.js",
"start": "http-server -c-1 ."
},
이것도 처음 수정했을 때만 잘 반영이 되고 그 이후로는 다시 캐시를 삭제해줘야만 했다
왜 그렇지...?
그래서 또 찾은 방법
index.html 의 script 태그에 ? 를 붙이고 문자열이나 숫자를 붙여주면 새로운 파일로 인식해서 바로 반영이 된다는 것
<script src="src/utils/validator.js?ver=33222"></script>
근데 이것도 저 ver 숫자를 계속 바꿔줘야만 새로운 파일로 인식하는 것 같다 ㅠㅠ
뭐가 문제일까 아직 찾는 중이지만 일단 이런 방법이 있다는 것을 남겨보려고 한다
# 백엔드 서버 실행 시 오류 발생
npm run start 로 백엔드 서버를 실행시켜야 하는데
> fe-assignment-lab-backend@1.0.0 start
> npm run crawling && node app.js
> fe-assignment-lab-backend@1.0.0 crawling
> node generateData
node:internal/modules/cjs/loader:1051
throw err;
^
Error: Cannot find module 'bluebird'
이런 오류가 발생했다
bluebird 는 어떤 라이브러리지?
npm install bluebird
로 설치해주고 다시 npm run start를 하니까 백엔드 서버가 정상적으로 돌아간다
# bluebird 라이브러리는 무엇을 하는걸까?
자바스크립트의 프로미스 라이브러리 중 하나
비동기 작업을 다루기 위한 표준인 Promise를 보완하고 하ㅗㄱ장하여 높은 효율성과 추가적인 기능을 제공
JS의 내장 Promise 기능의 한계를 보완하기 위해 bluebird와 같은 외부 라이브러리가 만들어졌다
즉, Promise 의 기능을 보완 및 확장하기 위한 라이브러리다
# 새로 알게 된 점
바닐라 자바스크립트로 컴포넌트를 구성해서 코드를 짜는 모든 방법을 새롭게 알게 되었다
처음 주어진 코드를 봤을 때는 구조가 어떻게 되어있는 것이고 코드의 의미도 이해하기 힘들었다
그치만 강의를 들으며 천천히 하나하나 따라해보니 반복되는 패턴이 있다는 것을 깨달았다
그렇게 해서 주어진 미션에 대한 해설을 듣고 이해할 수 있었다
하지만 바닐라 스크립트로 구성된 코드를 처음 접하다보니 더 많은 연습이 필요할 듯 하다
다음 강의에서도 새로운 기능들을 구현해보겠다
'TIL > 프로그래머스 데브코스' 카테고리의 다른 글
클라우딩 어플리케이션 엔지니어링 TIL Day 17 - 고양이 사진 검색 사이트 해설 (3) (0) | 2024.01.20 |
---|---|
클라우딩 어플리케이션 엔지니어링 TIL Day 16 - 고양이 사진 검색 사이트 해설 (2) (0) | 2024.01.19 |
클라우딩 어플리케이션 엔지니어링 데브코스 1기 월간 회고 1편 - 시작이 반이다 (0) | 2024.01.17 |
클라우딩 어플리케이션 엔지니어링 TIL Day 14 - 가계부 서비스 기능 개발하기 (0) | 2024.01.17 |
클라우딩 어플리케이션 엔지니어링 TIL Day 13 - 가계부 구현하기 (0) | 2024.01.17 |