개발 & IT/프론트엔드 (21) 썸네일형 리스트형 서버가 호출하는 API와 브라우저가 호출하는 API는 다르다 : NEXTJS 들어가며Next.js로 개발하다 보면 이런 상황을 마주친다. 분명히 서버에서 API를 잘 호출하고 있는데, 같은 주소를 클라이언트 컴포넌트에서 쓰면 요청이 실패한다. 로컬에서는 둘 다 되던 코드가, 배포하고 나면 클라이언트 쪽만 망가진다.이 글은 그 원인 — API를 누가 호출하느냐에 따라 동작이 달라지는 이유 — 을 설명한다.핵심 개념: API 호출의 주체Next.js 앱에서 API를 호출하는 주체는 두 가지다.서버: Server Component, API Route, Server Action 등에서 fetch()를 실행할 때. 코드는 Next.js가 돌아가는 머신에서 실행된다.브라우저: Client Component에서 fetch()를 실행하거나, 처럼 브라우저가 직접 리소스를 요청할 때. 코드는 .. Next.js 캐싱의 기본값과 동적 렌더링 전환 조건 Next.js의 렌더링 기본값Next.js 공식 문서(Glossary)는 다음과 같이 명시한다.Prerendering is the default for components that don't use Request-time APIs.즉, Request-time API를 사용하지 않는 컴포넌트는 기본적으로 빌드 시점에 HTML을 생성해 캐싱한다.dynamic 옵션의 기본값인 'auto'에 대한 설명도 같은 방향이다.The default option to cache as much as possible without preventing any components from opting into dynamic behavior.기본값이 "최대한 캐싱"이라는 것은 Next.js의 설계 방향을 직접적으로 보여준다.Req.. Next.js의 redirect() vs router.push() — nginx 리버스 프록시 + basePath 환경에서의 함정 배경Next.js App Router에서 로그인 후 대시보드로 이동시키는 코드를 작성할 때, 가장 먼저 떠오르는 방법은 Server Action에서 redirect()를 호출하는 것이다.// app/(auth)/login/actions.ts'use server'export async function login(prevState, formData) { // ... 로그인 처리 redirect('/dashboard') // 이게 문제가 됐다}로컬에서는 잘 동작한다. 그런데 nginx 리버스 프록시 뒤에 배포하는 순간, 로그인 후 /dashboard로 이동하려다 404가 발생했다. /admin/dashboard로 가야 하는데 /dashboard로 가고 있었다.Next.js의 basePath 설정이 프로젝.. Vue 개발자가 Next.js를 배우며 겪은 혼란: Server Component와 Client Component 이해하기 Vue와 Nuxt에 익숙한 개발자로서 Next.js를 처음 접했을 때, 가장 혼란스러웠던 부분은 "왜 데이터를 fetch 했는데 화면이 업데이트되지 않는가?"였습니다. Vue에서는 당연하게 작동하던 반응형 시스템이 Next.js에서는 전혀 다른 방식으로 동작했고, revalidatePath라는 낯선 함수를 호출해야 했습니다.이 글은 Vue/Nuxt 개발자가 Next.js의 Server Component와 Client Component를 이해하는 과정을 담았습니다.첫 번째 혼란: 왜 화면이 업데이트되지 않는가?Vue/Nuxt에서의 당연함Vue나 Nuxt에서 개발할 때, 반응형 시스템은 너무나 자연스럽게 작동합니다. {{ post.title }} 이 코드는 예상대로 작동합니다. 게시글을 추가하면 .. JavaScript 개발자가 Flutter의 copyWith를 이해하기까지 시작하며Flutter를 배우면서 가장 궁금했던 것 중 하나가 바로 copyWith 패턴이었습니다.// 이게 왜 안 되는 거지?deck.keyword = "커피"; // 컴파일 에러!// 왜 이렇게 해야 하지?final newDeck = deck.copyWith(keyword: "커피");"JavaScript였으면 그냥 바꾸면 되는데..." 라는 생각이 들었습니다. 하지만 실제로 사용해보니 이 패턴이 왜 필요한지 이해하게 되었고, 오늘은 그 내용을 공유하려 합니다.JavaScript에서는 당연했던 것들JavaScript(특히 React)로 개발할 때, 객체나 배열을 다루는 방식은 이랬습니다:// 객체 일부 변경const user = { name: "김철수", age: 30, email: "kim@exam.. Dart 메서드 vs Getter: 언제 무엇을 사용해야 할까? Flutter/Dart로 개발하다 보면 클래스의 속성에 접근하는 방법을 선택해야 할 때가 있습니다. 메서드로 구현할지, getter로 구현할지 고민되는 순간들이 있죠. 오늘은 이 둘의 차이와 올바른 선택 기준을 명확하게 정리해보겠습니다.1. 기본적인 차이점메서드 방식class Rectangle { double width; double height; // 메서드로 구현 double area() { return width * height; } double perimeter() { return 2 * (width + height); } Rectangle(this.width, this.height);}// 사용void main() { final rect = Rectangle.. TypeScript 인터페이스 확장: Declaration Merging과 Module Augmentation Next.js에서 NextAuth를 사용하여 인증 시스템을 구축하던 중, 다음과 같은 TypeScript 에러를 만났습니다.async session({ session, token }) { if (session.user) { session.user.id = token.id as string; // ❌ 에러! // Property 'id' does not exist on type } return session;}session.user에 id 속성을 추가하려고 했지만, TypeScript는 이 속성이 존재하지 않는다고 불평합니다. NextAuth의 기본 타입에는 name, email, image만 있고 id가 없기 때문이죠.이 문제를 해결하면서 TypeScript의 .. 웹 빌드 도구 비교: Webpack vs Vite vs Rollup 그리고 etc 모던 웹 개발에서 빌드 도구는 필수적입니다. 수많은 JavaScript 파일과 CSS, 이미지 등의 에셋을 최적화하고 번들링하여 브라우저가 효율적으로 로드할 수 있도록 만들어주죠. 하지만 선택지가 너무 많아서 어떤 도구를 써야 할지 고민되시나요? 이 글에서 주요 빌드 도구들을 비교하고, 여러분의 프로젝트에 가장 적합한 도구를 찾는 방법을 알려드리겠습니다.1. Webpack - 검증된 강자특징Webpack은 2012년부터 시작된 가장 성숙한 번들러입니다. 모든 것을 모듈로 취급하며, JavaScript뿐만 아니라 CSS, 이미지, 폰트 등 모든 에셋을 번들링할 수 있습니다.장점강력한 생태계: 수천 개의 플러그인과 로더 보유높은 커스터마이징: 복잡한 요구사항도 세밀하게 설정 가능코드 스플리팅: 동적 impo.. 이전 1 2 3 다음