프론트엔드 프로젝트 캠프 사전교육 1주차에는 자바스크립트 기본 문법을 다시 공부하는 시간을 가졌다. 자바스크립트를 이미 알고 있었지만 다시 공부하면서 새롭게 알게 된 것들이 있었다.
typeof null
을 콘솔창에 출력해보면 object가 나온다. 그 이유는 원래 객체 참조가 있어야 하는데 참조가 없음을 나타내는 값으로 만들어졌기 때문이다.
null 외에도 typeof []
과 같이 배열의 타입을 출력해봐도 object가 나온다.
그렇다면 배열의 타입은 배열, null의 타입은 null과 같이 정확한 타입을 출력하고 싶으면 어떻게 하면 될까?
Object.prototype.toString.call(null).slice(8, -1); // Null
Object.prototype.toString()
메서드를 사용하면 된다. 이 메서드는 객체를 [Object Type]
형태의 문자열로 표현하는 기능을 한다.
따라서 위의 코드는 '[Object Null]' 문자열의 8번째 글자부터 끝까지 잘라내는 역할을 한다. 따라서 'Null'이 출력된다.
console.log(Object.prototype.toString.call({})); // [object Object]
console.log(Object.prototype.toString.call([])); // [object Array]
console.log(Object.prototype.toString.call(new Date())); // [object Date]
console.log(Object.prototype.toString.call(null)); // [object Null]
console.log(Object.prototype.toString.call(undefined)); // [object Undefined]
console.log(Object.prototype.toString.call(123)); // [object Number]
console.log(Object.prototype.toString.call('Hello')); // [object String]
console.log(Object.prototype.toString.call(true)); // [object Boolean]
console.log(Object.prototype.toString.call(Symbol('sym'))); // [object Symbol]
NaN이 Not-A-Number를 의미하는 숫자 타입의 값이다. 숫자 타입이지만 숫자로 나타낼 수 없는 값이기에 NaN이라고 표시한다.
console.log(typeof NaN); // "number"
getter 함수와 setter 함수는 객체 속성의 값을 읽거나 설정할 때 사용한다.
getter 함수는 get 키워드를 이용하여 정의할 수 있고 setter 함수는 set 키워드를 이용하여 정의할 수 있다.
const person = {
firstName: "John",
lastName: "Doe",
get fullName() {
return `${this.firstName} ${this.lastName}`;
},
set fullName(name) {
[this.firstName, this.lastName] = name.split(" ");
},
};
console.log(person.fullName); // "John Doe"
person.fullName = "Jane Smith";
console.log(person.firstName); // "Jane"
console.log(person.lastName); // "Smith"
getter 함수와 setter 함수의 특징은 일반 함수처럼 소괄호를 열고 닫아 호출하는 것이 아니라 프로퍼티에 접근하는 방식과 동일하게 사용할 수 있다.
아토믹 디자인 패턴은 컴포넌트를 atoms / molecules / organisms / templates or pages로 나누어 설계한다.
const MainTemplate = ({ header, content, footer }) => (
<div>
{header}
<main>{content}</main>
{footer}
</div>
);
페이지(pages)는 템플릿에 실제 데이터를 적용한 것을 의미한다.
const HomePage = () => (
<MainTemplate
header={<Header />}
content={<HomeContent />}
footer={<Footer />}
/>
);
(이미지 출처: 9Diin의 엉망진창 개발시리즈)
만들고자 하는 날씨 앱 프로젝트의 결과물은 위와 같다.
리액트 수업을 진행하기 전, 혼자서 레이아웃 작업을 해보는 과제가 있었다.
내가 제출한 과제의 결과물은 아래 사진과 같다.
혼자서 레이아웃 작업을 하면서, 여러 번의 프로젝트를 제작한 경험이 있지만 여전히 버벅이는 것이 많아 배울 것이 많겠다고 느꼈다. 이 코드에서는 어떤 태그를 써야 하고 어떻게 스타일링을 하는게 맞는지 헷갈리는 일이 많았다.
수업을 들으면서 차근차근 컴포넌트를 구성했는데, 그 과정에서 어떤 흐름으로 컴포넌트를 분리하는 것이 좋을지 다시 한 번 감을 잡게 되었다.
그리고 컴포넌트를 분리하고 파일을 관리하는 과정에서 어떤 구조로 파일을 관리할 수 있을지에 대해서도 고민할 수 있었다.
수업을 수강한 후에 배운 내용을 바탕으로 과제 코드를 리팩토링 하는 과제가 주어졌다. 나는 과제를 진행하면서 아토믹 디자인 패턴을 적용해보았다.
컴포넌트 파일들을 직접 atoms, molecules, organisms로 구분하면서 감을 익혀보기도 하고 고민할 수 있는 시간을 가져서 의미있었다.
날씨 앱에서 전역 상태를 관리하는 라이브러리로 Jotai를 사용했다. 나는 Recoil을 사용해본 경험이 있기 때문에 구조가 비슷한 Jotai를 사용하기에는 용이했다.
데이터가 여러 컴포넌트에 걸쳐 전역적으로 사용되기 때문에 전역 상태 관리가 필요하다. 이 앱에서 필요한 전역 상태는 지역에 관한 상태이다. 날씨 검색 지역에 따라 모든 컴포넌트에서 출력되는 결과물이 달라질 것이기 때문이다.
import { atom } from 'jotai';
export const cityNameAtom = atom<string>('seoul');
도시 이름을 atom을 이용하여 전역 상태로 관리할 수 있게 한다. atom은 쉽게 말해 하나의 전역 상태를 만든다고 생각하면 된다.
그리고 이 atom을 사용하기 위해서는 useAtom 훅을 사용하면 된다.
import { useEffect, useState } from 'react';
import { useAtom } from 'jotai';
...
import { cityNameAtom } from '@/store';
function HomePage() {
...
const [cityName] = useAtom(cityNameAtom);
useEffect(() => {
fetchApi(cityName, setWeatherData);
fetchTideApi(cityName, setTideData);
getOneWeekWeather(cityName, setOneWeekWeatherSummary);
}, [cityName]);
return (
<div className="page bg-gray-200">
<div className="page__container">
<Header />
<div className="w-full flex flex-col items-center justify-start pb-6 px-6 gap-6">
{/* 상단 3개의 위젯 */}
<div className="w-full flex items-center gap-6">
<TodayWidget data={weatherData} />
<HourlyWidget data={weatherData.forecast.forecastday[0]} />
<MapWidget />
</div>
{/* 하단 2개의 위젯 */}
<div className="w-full flex items-center gap-6">
<HighlightsWidget tideData={tideData} currentData={weatherData} />
<WeeklyWidget data={oneWeekWeatherSummary} />
</div>
</div>
</div>
</div>
);
}
export default HomePage;
Recoil도 간편하게 전역 상태 관리를 할 수 있지만 <RecoilRoot>
로 컴포넌트를 감싸는 일을 따로 해주어야 한다. Jotai에서는 그런 단계를 하지 않아도 쉽게 전역 상태를 사용할 수 있다.
아직 Jotai Documents를 다 읽어보지 않아서 다 알지는 못하지만 Recoil과 비슷하고 더 간단한 라이브러리로 보였다. 추후에 Jotai에 대해서도 정리하는 시간을 가져보도록 하겠다.
본 후기는 [유데미x스나이퍼팩토리] 프론트엔드 프로젝트 캠프 과정(B-log) 리뷰로 작성 되었습니다.