✅ 오늘 한 일
자꾸 헷갈리는 번들과 빌드의 차이
webpack은 번들러일까, 빌드할 때 쓰는 도구인가 ?
turbopack은 번들러일까, 빌드할 때 쓰는 도구인가 ?
- 번들러
기존 문제점
- 전역 범위를 갖는 수백 개의 자바스크립트 파일의 중복 선언
- 수백 개에 달하는 자바스크립트 파일로 인한 느린 로딩
- 수동적인 웹 개발 루틴 (파일, 이미지 압축 / CSS 전처리기 변환 등)
웹 애플리케이션을 구성하는 모든 자원을 하나의 파일로 묶는 도구.
- 모듈 단위의 코드 작성
- 네트워크 병목 완화 (최적화)
- 웹 개발 작업 자동화
웹팩은 번들러임.
하나의 웹 서비스를 구성하는 파일들을 해석한 다음 하나의 파일로 합쳐주는 역할을 함.
그러니까 웹팩이 하는 역할인 번들링은 빌드의 한 작업 단계인 거지.
- 빌드
개발 코드를 실제 배포 가능한 형태로 만드는 전체 과정
여러 작업들의 집합임.
예를 들면,
- TypeScript -> JavaScript 트랜스파일
- SCSS -> CSS 전처리
- import/export 구조를 하나로 묶는 번들링
- 코드 난독화, 압축, 최적화
- 이미지/폰트 등 정적 자산 복사
이런 전체 과정을 통틀어 "빌드"라고 함.
구체적인 상황을 예를 들면
TypeScript로 작성된 여러 개의 모듈이 있을 떄,
트랜스파일 (typescript -> javascript) 가 먼저 일어나고, 그 결과물(js)를 번들러가 묶음.
트랜스파일 -> 번들링 -> 최적화 -> 출력
webpack은 번들러일까, 빌드할 때 쓰는 도구인가 ?
turbopack은 번들러일까, 빌드할 때 쓰는 도구인가 ?
를 물어보면 둘 다 맞다. 번들러이고, 번들러는 빌드할 때 쓰는 도구임.
HMS에서 next를 쓰고 버전이 14이므로 webpack을 쓰는데, 로컬에서 실행하는 속도가 너무 느려서 고민하던 중 next에서 공식 지원하는 turbopack이 빠르다고 해, 업데이트를 했다.
그런데 별 생각 없이
npm i next@latest react@latest react-dom@latest
하니까 next 16이 설치되어 있었다 ; 아오 공식 문서를 잘 읽어보자 ...ㅜ
그래서 하 이렇게 저렇게 뭐 설정하면서 돌려보는데, turbopack을 적용해보니까 아주 박살남.
아으 어지러..
일단 사전 설정은
- webpack 설정을 turbopack으로 옮기기 (svgr, storybook 빌드 과정에서 제외)
- 잃어버린 withPWA ... 이거 다시 찾아야 함. <- ❗❗❗
const nextConfig: NextConfig = {
turbopack: {
rules: {
'*.svg': {
loaders: ['@svgr/webpack'],
as: '*.js',
},
},
},
이제부터 트러블 슈팅 하면서 변경 사항 찾기
- Error: Route "/detail/[cardName]" used
params.cardName.paramsis a Promise and must be unwrapped withawaitorReact.use()before accessing its properties. Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis
params 불러올 때 Promise 고, await 로 감싸줘야 함.
아래처럼
async function Page({ params }) {
// asynchronous access of `params.id`.
const { id } = await params
return <p>ID: {id}</p>
}
내 코드에서 이렇게 있던 걸
const info = pageInfo[params.cardName]
이렇게 변경해주고, 선언부에 async와, 반환 타입 Promise도 적용해줌.
const info = pageInfo[(await params).cardName]
ssr: falseis not allowed withnext/dynamicin Server Components. Please move it into a Client Component.
const RobotErrorListCard = dynamic(() => import('@/containers/dashboard-page/summary-section/RobotErrorListCard'), {
ssr: false,
})
이거 안된다 함.
일단 {ssr: false}를 왜 붙인거냐면 , 저 컴포넌트에서 서버 사이드 렌더링을 비활성화 함.
이 옵션은 다음과 같은 이유로 사용:
- 브라우저 전용 API 사용
- window, document, navigator
- 지도 라이브러리
- 캔버스/WebGL 사용
- 서버에서 불가능한 컴포넌트
// 예: window 객체 사용
const width = window.innerWidth // 서버에서 에러
```
3. 번들 크기 최적화
1. 초기 로딩 시 해당 컴포넌트를 제외
2. 클라이언트에서만 로드
next 15에서부터는 ssr:false 옵션이 deprecated 됨.
명시적으로 "use client"를 사용해야 함.
하면 일단 변경 끗.
근데 이제 페이지 이동하면서 확인해보니까 문제 발생함.
![[Pasted image 20251111182412.png|Pasted image 20251111182412.png]]
데이터 조회를 하는데 대단한 요청을 한다.
```ts
const { data: motorTempData, isLoading: motorTempIsLoading, dataUpdatedAt: motorTempUpdatedAt } = useGetMotorTemp(params.mapId, robotId, {
startDate: params.startDate,
endDate: params.endDate,
period: params.startDate && params.endDate ? 'custom' : 'hour',
})
const { data: motorCurrentData, isLoading: motorCurrentIsLoading } = useGetMotorCurrent(params.mapId, robotId, {
startDate: params.startDate,
endDate: params.endDate,
period: params.startDate && params.endDate ? 'custom' : 'hour',
})
const { data: motorVoltageData, isLoading: motorVoltageIsLoading } = useGetMotorVoltage(params.mapId, robotId, {
startDate: params.startDate,
endDate: params.endDate,
period: params.startDate && params.endDate ? 'custom' : 'hour',
})
const { data: batteryVoltageData, isLoading: batteryVoltageIsLoading } = useGetBatteryVoltage(params.mapId, robotId, {
startDate: params.startDate,
endDate: params.endDate,
period: params.startDate && params.endDate ? 'custom' : 'hour',
})
쿼리에서 매 렌더링마다 새 객체를 생성해 queryKey가 계속 바뀌는 것이 원인.
queryKey가 바뀌면 새로운 요청 발생하고, 이 루프를 무한 반복.
params 객체를 메모이제이션
const detectionParams = useMemo(
() => ({
startDate: params.startDate,
endDate: params.endDate,
period: (params.startDate && params.endDate ? 'custom' : 'hour') as 'custom' | 'hour',
}),
[params.startDate, params.endDate]
)
근데 계속 요청함. 진자 원인 뭐지 ????????????????? 아마 next 업데이트 하면서 새로운 뭔가가 생긴ㄱ ㅓㅅ 같다......
--
turbo pack 사용 후기
진자 감동이다 ... 이거 왜 지금 썼지
로컬에서 돌리는데 배포한 서버에서 쓰는 것 같다