티스토리 뷰
이전에 `Quick-News` 프로젝트에서 Lighthouse로 성능을 분석한 결과를 작성한 적이 있었다. 그리고, `Performance` 점수를 제외한 나머지 3개 부분의 점수를 100점으로 개선한 적이 있었다.
그리고 나서, `Perforamnce` 점수 개선을 시도했다. 여기서 현재 내 컴퓨터는 10년이 되어 성능 상 문제가 많다. 그래서 모든 문제를 해결하기 어렵기 때문에 최대한 개선이 가능한 부분들만 개선하기로 결정했다.
`Performance` 점수 개선을 위해 우선 문제점을 파악하였다. 페이지 렌더링 시간을 개선할 필요가 있었고, 기존에 CSR 방식 대신 초기 렌더링이 빠른 SSR 방식으로 초기 데이터를 불러오는 전략을 선택하기로 결정했다. 초기 렌더링 시간은 `Performance`에 영향을 주기 때문이다.
현재 `네이버 검색 API`를 사용해 뉴스 데이터를 가져오는 페이지를 첫 페이지로 구현하였다. 기존 CSR 방식으로 데이터를 로드한 후, 화면에 나타냈다. CSR 방식은 초기 렌더링은 느리지만, 이후 빠른 렌더링이 가능하고 비교적 많이 사용했던 방식이었기 때문에 선택했었다. 그러나 초기 로드 시간이 상대적으로 길기 때문에 Lighthouse의 `Performance` 점수에 영향을 미친 것 같았다.
이를 보완하기 위해 SSR 방식을 도입하기로 결정했고, `getServerSideProps`를 사용해 데이터를 가져오도록 수정했다.
SSR 방식을 도입하기 전에 기존 CSR 방식으로 초기 페이지에 나타내는 `네이버 검색`에서 가져온 뉴스 데이터는 아래의 코드를 사용해서 요청하도록 했다. `CORS` 문제가 발생할 가능성이 존재하기 때문에 `Proxy` 설정을 하여 문제없이 데이터를 가져오도록 선언했다.
export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
const { query } = req
res.setHeader('Access-Control-Allow-Origin', '*')
try {
const apiResponse = await axios.get(
`https://openapi.naver.com/v1/search/news.json`,
{
headers: {
'X-Naver-Client-Id': process.env.NEXT_PUBLIC_CLIENT_ID,
'X-Naver-Client-Secret': process.env.NEXT_PUBLIC_CLIENT_SECRET,
},
params: {
query: query.q,
display: query.pageCount,
start: 1,
sort: 'sim',
},
},
)
res.status(200).json(apiResponse.data)
} catch (error) {
if (process.env.NODE_ENV !== 'production') {
console.error('네이버 뉴스 데이터 불러오기 에러', error)
}
res.status(500).json({ message: 'Internal Server Error' })
}
}
그리고 나서 `handler`의 경로를 사용하여 (`/api/naver-news-proxy`) `query` 값에 맞는 데이터를 가져올 수 있도록 요청하였다.
const { data } = await axios.get<NaverNewsLists>('/api/naver-news-proxy', {
params: {
q: queryValue,
pageCount: MAX_PAGE_COUNT,
},
})
return data.items
그 다음에 기존에는 CSR 방식을 사용해서 해당 데이터를 사용할 컴포넌트에서 API 데이터를 요청한 뒤 전달받은 데이터 중에서 `items`의 배열 값을 내보내는 Fetch 함수를 사용해 처리했다.
이렇게 CSR 방식을 사용해서 데이터 로드를 시도했다. 데이터를 가져오는 데 문제는 없었지만 초기 렌더링이 느리다는 단점이 있었다. 그래서 이를 개선하기 위해 SSR 방식으로 코드를 수정했다. (구글 검색을 통해서 자주 쓰이는 SSR 방식의 코드를 참고하여 수정했다.)
export default function NewsList({...}: ...) {
...
}
export const getServerSideProps: GetServerSideProps<NewsDataProps> = async (
context,
) => {
const pageSize = 40;
const queryValue = '오늘의주요뉴스';
try {
const { data } = await axios.get(`/api/naver-news-proxy`, {
params: {
q: queryValue,
pageCount: pageSize,
},
headers: {
'X-Naver-Client-Id': process.env.NEXT_PUBLIC_CLIENT_ID,
'X-Naver-Client-Secret': process.env.NEXT_PUBLIC_CLIENT_SECRET,
},
});
return {
props: {
initialNews: data.items,
initialPageSize: 10,
},
};
} catch (error) {
console.error('뉴스 데이터 가져오기 실패', error);
return {
props: {
initialNews: [],
initialPageSize: 10,
},
};
}
};
위 코드와 비슷하게 작성하여 SSR 방식으로 코드를 수정했다. 수정된 코드로 페이지가 새로고침이 되었음에도 불구하고 데이터가 로드되지 않아 `Skeleton`의 로딩 상태만 나타났다.
"혹시 오류가 발생했나?"
오류가 발생한 줄 알았으나, 콘솔이나 터미널에도 에러 메시지가 없었다. 그래서 우선 API가 제대로 호출되고 있는지 확인하기 위해서 `console.log`를 추가하여 확인하였다.
export const getServerSideProps: GetServerSideProps<NewsDataProps> = async (
context,
) => {
const pageSize = 40;
const queryValue = '오늘의주요뉴스';
console.log('getServerSideProps 실행됨 - API 호출 시작');
try {
const { data } = await axios.get(`/api/naver-news-proxy`, {
params: {
q: queryValue,
pageCount: pageSize,
},
headers: {
'X-Naver-Client-Id': process.env.NEXT_PUBLIC_CLIENT_ID,
'X-Naver-Client-Secret': process.env.NEXT_PUBLIC_CLIENT_SECRET,
},
});
console.log('API 응답 성공:', data);
return {
props: {
initialNews: data.items,
initialPageSize: 10,
},
};
} catch (error) {
console.error('뉴스 데이터 가져오기 실패', error);
return {
props: {
initialNews: [],
initialPageSize: 10,
},
};
}
};
하지만, `console.log`를 추가하고 나서 다시 확인을 해봐도 여전히 데이터는 로드되지 않았고, 로그 메시지도 나타나지 않았다. `getServerSideProps` 방식 외에 다른 방식이 있는지 검색하였고, `Next.js` 13버전에서 제공하는 `fetch`로 데이터를 가져오는 방법을 시도했다.
export default async function getData() {
const pageSize = 40;
const queryValue = '오늘의주요뉴스';
const url = `/api/naver-news-proxy?q=${queryValue}&pageCount=${pageSize}`;
const headers: HeadersInit = {
...(process.env.NEXT_PUBLIC_CLIENT_ID && {
'X-Naver-Client-Id': process.env.NEXT_PUBLIC_CLIENT_ID,
}),
...(process.env.NEXT_PUBLIC_CLIENT_SECRET && {
'X-Naver-Client-Secret': process.env.NEXT_PUBLIC_CLIENT_SECRET,
}),
};
const response = await fetch(url, {
method: 'GET',
headers,
cache: 'no-cache',
});
if (!response.ok) {
if (response.status === 404) {
throw new Error('페이지를 찾을 수 없습니다.');
} else if (response.status >= 500) {
throw new Error('서버 오류가 발생했습니다.');
} else {
throw new Error(`뉴스 데이터를 가져오지 못했습니다. ${response.status}`);
}
}
const data = await response.json();
return { initialNews: data.items, initialPageSize: 10 };
}
export default async function NewsList() {
const { initialNews, initialNews } = await getData();
...
}
`fetch`로 데이터를 가져오되 `cache: 'no-cache'`를 설정해야 SSR 방식으로 데이터를 가져올 수 있는 방법이었다. 그러나, 이 방법 역시 데이터를 불러오지 못했다. 물론 에러도 발생하지 않았다.
여러 시도를 하였음에도 불구하고 SSR 방식으로 데이터를 가져오는 것은 현재로써 결과적으로 실패가 됐다. `네이버 검색 API`를 다른 서버를 통하지 않고 직접 사용할 경우에 SSR 방식이 제대로 동작하지 않는 건지 궁금해졌다. 그래서 구글 검색으로 비슷한 시도를 한 사람들의 블로그를 확인해봤지만, SSR 방식이 아닌 CSR 방식으로 `네이버 검색 API`의 데이터를 가져오고 있었다. 그리고 `네이버 개발자 포럼`에서 관련 질문을 올렸지만 아직 어떤 답변을 보지 못했다.
아직 정확한 원인을 찾지 못했지만, 우선 기존 CSR 방식으로 돌아가 코드를 최적화하여 성능 개선을 시도하면서 다른 해결 방법을 찾을 계획이다.
비록, 모든 시도들이 현재 실패하였지만, 앞으로 해결 방법을 찾지 못하더라도 이 문제를 해결하기 위해 많은 시간동안 여러가지 시도를 하며 많이 고민하고 집중했던 시간이었다. 이 시간이 또 다른 문제를 해결하는 데 도움이 됐으면 좋겠다.
'프론트엔드 > NextJS' 카테고리의 다른 글
[No 테크] Next.js에서 Lighhouse의 Performance 점수 개선은 정말 어렵다 (0) | 2024.10.29 |
---|---|
이제서야 깨달은 SSR로 데이터 가져오기 (0) | 2024.10.05 |
첫 Lighthouse 개선기 (Accessibility/Best Practices/SEO) (1) | 2024.09.07 |
퀵뉴스 프로젝트, 검색 요청 개선기 (0) | 2024.02.16 |
CSR, SSR, SSG, ISR 비교 (0) | 2023.06.14 |
- Total
- Today
- Yesterday
- Singleton
- 포스텍애플디벨로퍼아카데미
- 코딩테스트 대비
- 최종추가합격
- 그룹인터뷰후기
- 싱글톤
- 스프링
- 원티드 프리온보딩 챌린지
- 설명회느낌점
- 개발자이력서꿀팁
- DB Error MongooseServerSelectionError
- 자바스크립트
- 신입개발자가 준비해야 할 것들
- 포스텍애플아카데미
- 원티드 프리온보딩
- Default Branch
- LottieFiles
- if(kakao)dev2022
- React
- 개발 이력서 지원 팁
- node
- 깃허브 Merge
- PostechAppleDeveloperAcademy
- javascript
- 조코딩과함께
- 고민한 부분
- 프론트엔드 챌린지
- Express
- #포스텍애플디벨로퍼아카데미
- Frontend
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |