2024.11.12 - [분류 전체보기] - [ KISA ] Next.js를 활용한 검색 최적화 대응 웹사이트 구축하기(1)
▶ Next.js 프로젝트 생성하기[만들기]
1. 터미널에 'npx create-next-app@latest' 입력한 뒤 엔터치기
- npx에게 최신버전으로(@latest) Next.js 어플리케이션을 만들어달라고 명령하는 것
- 자동으로 모든 것을 설정해주는 create-next-app 을 사용해서 새로운 Next.js 어플리케이션을 시작하는 것을 추천한다.
2. 설치중에 다음의 프롬프트(운영체제가 사용자에게 보여주는 메시지)에 응답하기
[ yes 또는 no로 생성할 Next.js 어플리케이션에 대한 초기 설정하기 ]
What is your project named? my-app
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like your code inside a `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to use Turbopack for `next dev`? No / Yes
Would you like to customize the import alias (`@/*` by default)? No / Yes
What import alias would you like configured? @/*
위 질문에 대한 설정이 완료되면 새로운 Next.js 프로젝트(어플리케이션, app)가 만들어진다.
- 문서에는 나오지 않았던 프롬프트가 생겼다.
Would you like to use Turbopack for next dev?
Turbopack을 Next.js 프로젝트 개발에 사용하겠냐고 물어보는 건데, Turbopack은
자바스크립트와 타입스크립트에 최적화된 an incremental bundler(점진적 번들러: 전체 프로젝트를 처음부터 끝까지 번들링 하는 것이 아니라 변경된 부분만 다시 번들링하는 방식을 의미한다) 로, Rust로 작성되었으며, Next.js에 내장되어 있다고 한다.
→ yes라고 함, 지금은 대략적인 개념만 익혀두고 다음에 Turbopack에 대해 공부해볼 것
실습
생성된 Next.js 실행하기: 터미널에서 'npm run dev' 입력한 후 엔터치기 → 생성된 Next.js 어플리케이션에 접속할 수 있는 웹 주소를 알려준다 → Local: http://localhost:3000 해당 주소를 웹 브라우저 주소창에 입력하면 된다.
▶ Next.js 어플리케이션 개발실습_코드 작성하기
(feat. Next.js의 기능들을 익혀보기)
코드 실습
/* eslint-disable react/jsx-key */
// 동적 주소 처리 방식
// query string / search params 주소?key=value&key2=value2(url encoded / encoded url)
// url params
// localhost:3000/?targetDt=20241112
import dayjs from 'dayjs';
import PrevButton from './PrevButton';
type Props = {
searchParams: {
targetDt?: string;
};
};
const today = dayjs().subtract(1, 'day').format('YYYYMMDD');
// 서버 컴포넌트는 async function으로 선언하여
// 클라이언트 컴포넌트와 구별하기
export default async function Home({
searchParams: { targetDt = today },
}: Props) {
// 영화진흥위원회 오픈 api를 사용해서 데이터 로드하기
// 매개변수로 전달하는 key와 targetDt는 필수다.
const key = '발급받은 영화진흥위원회 오픈 api 키를 입력해주세요';
// const targetDt = '20241112';
const baseUrl =
'http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json';
const url = `${baseUrl}?key=${key}&targetDt=${targetDt}`;
// 데이터를 요청한다.
const response = await fetch(url);
// 요청 데이터의 응답은 json 형식이고, json을 파싱해야 한다.
const json: ResponseType = await response.json();
// console.log(JSON.stringify(json, null, 2));
// const char = 'a'; // string
// const chars = ['a', 'b', 'c', 'd'];
// JSX가 반환할 수 있는 유형
// 1. Primitive 타입 데이터(number, string, boolean)
// 2. JSX Node
// 3. 1 혹은 2로 구성된 배열
// console.log(`dayjs(targetDt): ${dayjs(targetDt).format('YYYY년 MM월 DD일')}`);
// console.log(`targetDt: ${targetDt}`);
return [
<div className='w-[500px] mx-auto'>
<div className='flex justify-between'>
{/* <a
href={
'?targetDt=' + dayjs(targetDt).subtract(1, 'day').format('YYYYMMDD')
}
>
이전
</a>*/}
{/* <button onClick={() => {}}>이전</button> */}
<PrevButton targetDt={targetDt} />
{dayjs(targetDt).format('YYYY년 MM월 DD일')}
<button>다음</button>
</div>
<ol className='divide-y *:py-4 mt-4'>
{/* <li>{json.boxOfficeResult.dailyBoxOfficeList[0].movieNm}</li>
<li>{json.boxOfficeResult.dailyBoxOfficeList[1].movieNm}</li>
<li>{json.boxOfficeResult.dailyBoxOfficeList[2].movieNm}</li> */}
{/* {[
<li>{json.boxOfficeResult.dailyBoxOfficeList[0].movieNm}</li>,
<li>{json.boxOfficeResult.dailyBoxOfficeList[1].movieNm}</li>,
<li>{json.boxOfficeResult.dailyBoxOfficeList[2].movieNm}</li>,
]} */}
{json.boxOfficeResult.dailyBoxOfficeList.map((item: ItemType) => (
// 객체 movie를 하나씩 받아서
<li key={item.rank}>
{item.rank}위 - {item.movieNm}{' '}
{/* {item.rankOldAndNew === 'OLD' ? (
<span className='text-xs'>({item.rankOldAndNew})</span>
) : (
''
)} */}
{item.rankOldAndNew === 'NEW' && (
<span className='text-xs text-red-500'>N</span>
)}
</li>
))}
</ol>
<pre>
<code>{JSON.stringify(json, null, 2)}</code>
</pre>
</div>,
];
}
type ResponseType = {
boxOfficeResult: {
boxofficeType: string;
showRange: string;
dailyBoxOfficeList: ItemType[];
};
};
type ItemType = {
rnum: string;
rank: string;
rankInten: string;
rankOldAndNew: string;
movieCd: string;
movieNm: string;
openDt: string;
salesAmt: string;
salesShare: string;
salesInten: string;
salesChange: string;
salesAcc: string;
audiCnt: string;
audiInten: string;
audiChange: string;
audiAcc: string;
scrnCnt: string;
showCnt: string;
};
'use client';
import dayjs from 'dayjs';
// useSearchParams,
import { useRouter } from 'next/navigation';
// import { useRouter } from 'next/router';
type Props = {
targetDt: string;
};
export default function PrevButton({ targetDt }: Props) {
// const searchParams = useSearchParams();
const router = useRouter();
return (
<button
onClick={() => {
// console.log('click');
// const date = searchParams.get('targerDt');
// dayjs(date).subtract(1, 'day').format('YYYYMMDD');
router.push(
`?targetDt=${dayjs(targetDt).subtract(1, 'day').format('YYYYMMDD')}`
);
}}
>
이전
</button>
);
}
▶ 코드 공부
Array.prototype.map()
XML 파트(함수 컴포넌트의 return에 해당하는 부분) 에서 JSX Node로 구성된 배열을 자바스크립트 코드로 하나씩 꺼낼 때
Array.map 함수를 사용할 수 있다. Array.map 함수는 배열을 이용해서 일괄적인 처리를 한 후에 최종 값으로 배열을 반환한다.
map() 메서드는 배열 내의 각 요소에 대해 주어진 함수를 적용하고, 그 결과를 모아 새로운 배열을 반환한다.
map은 콜백함수를 각각의 요소에 대해 한 번씩 순서대로 호출해서 그 함수의 반환 값으로 새로운 배열을 만든다.
콜백 함수는 (undefined도 포함해서) 배열 값이 들어있는 인덱스에 대해서만 호출된다.
값이 삭제되거나 아직 값이 할당/정의되지 않은 인덱스에 대해서는 콜백함수가 호출되지 않는다.
async, await, fetch
The Fetch API는 HTTP 요청과 응답하는 일련의 과정을 가능하게 해주는 자바스크립트 인터페이스를 제공한다.
Fetch는 현대에 XMLHttpRequest(xhr)대신 사용한다. 콜백 기반 방식인 XMLHttpRequest와 달리
Fetch는 현대 어플리케이션의 특징을 가진? promise 기반 방식으로 네트워크와 통신한다.
└ service worker와 CORS
Fetch API에서 fetch() 함수는 네트워크로 데이터?를 요청할 때 사용하는 함수다.
fetch하기 위해 요청을 구성하기 위한 선택적인 매개변수와 함께 요청 객체 또는 url을 포함한 문자열을 전달한다.
fetch() 함수는 기본적으로 URL만 필요하지만, 요청을 더 세밀하게 설정하려면 두 번째 인자를 추가할 수 있다.
fetch() 함수는 서버의 응답을 나타내는 Response 객체를 가진 이행가능한 Promise를 반환한다.
요청 상태를 확인한 후에 응답에 적당한 메소드를 호출함으로써
text 그리고 JSON을 포함하여 다양한 포맷형식으로 응답의 본문을 추출할 수 있다.
URL을 포함하는 문자열을 선언하고, fetch() 함수를 호출한다.
// 영화진흥위원회 오픈 API 기본 요청 url
const baseUrl = 'http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json';
// 영화진흥위원회 오픈 API를 사용하여 일별 박스오피스 데이터를 얻기 위해서는
// 기본적으로 기본 요청 url과 발급받은 key와 조회하고자 하는 날짜의 값이 필수다.
// 그래서 key와 조회하고자 하는 일자 또한 변수에 담고, 요청 url을 조합하여 fetch() 함수로 데이터를 요청하고자 한다.
const key = '영화진흥위원회 오픈 API 사용을 위해서 발급받은 키값';
const targetDt = '요청하고자 하는 일자'; // 일자 형식은 'YYYYMMDD'여야 한다.
// 요청할 url 조합
const url = `${baseUrl}?key=${key}&targetDt=${targetDt}`;
// 네트워크를 통해 데이터를 요청하기
const response = await fetch(url);
// 네트워크를 통해 응답받은 데이터의 통신 상태를 확인해보기
// response.ok의 값은 boolean 타입으로 200번대면 통신이 잘 이루어졌다는 것
// true가 아니라면 통신이 잘 이루어지지 않았다는 것, 응답 상태(response.status)를 확인한다.
if(!response.ok) {
throw new Error(`Response status: ${response.status}`);
}
// 요청 데이터의 응답은 json 형식이고, json을 파싱한다[사람이 읽을 수 있는 상태로 변환한다]
const json = await response.json();
// javascript 객체나 값을 JSON 문자열로 변환하는 메소드다.
// JSON.stringfy(value, replacer, space); → value는 JSON으로 변환할 값 ex. 객체나 배열 등
// replacer(선택사항) 변환할 객체의 특정 프로퍼티만 포함하거나 제외하고 싶은 경우에 사용할 수 있는 함수나 배열,
// 여기서는 null을 기입함으로써 모든 프로퍼티가 포함된 JSON 문자열이 생성된다.
// 세번 째 인자인 space 자리에 2를 작성함: 출력된 JSON 문자열에 들여쓰기 적용하여 사람이 읽기 쉽도록 만든다.
console.log(JSON.stringfy(json, null, 2));
▶ JSX의 특징
함수 컴포넌트는 JSX Node를 반환한다.
JSX가 반환할 수 있는 유형
1. Primitive 타입 데이터 (number, string, boolean)
2. JSX Node
3. 1 혹은 2로 구성된 배열
▶ 라이브러리
Day.js
Day.js a minimalist 자바스크립트 라이브러리다. Day.js 라이브러리는 문자열을 날짜 형식으로 변환하는 기능(parses),
날짜가 유효한지 체크하는 기능(validates), 날짜를 조작하는 기능 예를 들면 날짜를 더하거나 빼는 기능 등,
날짜와 시간을 사람이 알 수 있는 형식으로 출력하는 기능들을 갖고 있다. Day.js 라이브러리는 최신 웹 브라우저에서
잘 작동하도록 만들어졌다.
Node.js 프로젝트에서 Day.js 라이브러리를 사용하려면
터미널에서 npm install dayjs 를 입력하거나
script(파일)에 포함하여 바로 사용할 수 있는 방법이 있다고 한다(←스크립트에 라이브러리를 포함하여 사용하는 방법은 안해봄)
```
const dayjs = require('dayjs');
dayjs().format();
```
console.log(dayjs()); // Wed, 13 Nov 2024 08:53:20 GMT
// 2024-11-13T17:55:32+09:00 → 생성된 날짜 및 시간 객체에서 format() 메서드를 호출해야 한국시간에 맞게 출력된다.
console.log(dayjs().format());
const yesterDay = dayjs().subtract(1, 'day').format('YYYYMMDD');
dayjs()로 얻는 값은 오늘 날짜와 시간, 여기서 subtract() 메서드를 사용하면 지정한 단위의 숫자만큼 뺄 수 있다.
day(일자)를 단위로 1(하루)를 빼고 그리고 format() 메서드를 호출하여 'YYYYMMDD' 형식으로 만들어 그 값을 yesterDay 변수에 담는다. 그래서 결과는 오늘자를 기준으로(금일 2024년 11월 13일) 하루를 뺀 값 어제의 날짜가 전달한 날짜 형식에 맞게 포맷되어 출력된다 → 20241112
▶ 동적 처리 주소 방식
1. query string / search params → ex. 주소?key=value&key2=value2 (url encoded / encoded url)
URLSearchParams 인터페이스는 URL에 붙은 쿼리 문자열을 쉽게 다룰 수 있게 도와주는 여러가지 메서드를 제공한다.
이를 통해 쿼리 문자열의 값을 추가, 수정, 삭제 그리고 파라미터를 추출할 수 있다.
쿼리 문자열은(query string) URL에서 ?(물음표) 뒤에 위치한 부분으로 주로 웹 요청에서 데이터나 파라미터를 전달할 때 사용된다.
쿼리 문자열은 한 쌍의 key와 value 그리고 한 쌍의 key와 value가 여러 개 있을 때 &(엠퍼센드) 기호로 연결되어 구성된다.
2. url params
▶ 클라이언트 컴포넌트의 위치
ver1.
- / page-name
- page.tsx
- PrevButton.tsx
- NextButton.tsx
ver2.
- / app
- / page-name
- page.tsx
- / components
- / ui
- PrevButton.tsx
- NextButton.tsx
▶ 오류 혹은 에러
Disable react/jsx-key
▶ 자바스크립트에서 값 할당할 때 팁!
1. const key = condition || 'value'; // condition이 거짓일 때 'value'가 key에 할당된다.
2. 삼항 연산자 사용
const key = condition? ' 1 ' : ' 2 '; // condition이 참일 때 key에 '1'이 거짓일 때 '2'가 할당된다.
3. && 연산자 사용
ex. XML 파트에서
{ item.rankOldAndNew === 'NEW' && <sapn className="text-xs text-red-500">N</span> }
이렇게 작성하면 item.ranOldAndNew의 값이 'NEW'가 참이라면 && 연산자를 기준으로 우항의 연산을 진행한다.
그래서 좌항이 참이면 우항의 span태그를 화면에 출력하는 것을 진행하고, span태그의 내용물로는 N이 작성되게 된다.
▶ 터미널에서 사용하는 명령어
- 현재 디렉토리명 확인하기: pwd
pwd는 printing working directory 의 약어, 현재 작업중인 폴더의 절대 경로를 알려준다[출력한다]
- 현재 디렉토리의 파일 목록 확인하기: ls
'공부기록용' 카테고리의 다른 글
[ KISA ] Next.js를 활용한 검색 최적화 대응 웹사이트 구축하기(3) (6) | 2024.11.15 |
---|---|
[ javascript ] 자바스크립트에서 네트워크 통신하는 법 (XMLHttpRequest) (9) | 2024.11.14 |
[ KISA ] Next.js를 활용한 검색 최적화 대응 웹사이트 구축하기(1) (1) | 2024.11.12 |
[ javascript ] 두서없는 공부 기록 (0) | 2024.11.11 |
[ javascript ] nullish 병합 연산자(??), 쿵쿵따 게임 실습 (2) | 2024.11.09 |