본문 바로가기

개발 & IT/프론트엔드

(22)
Next.js Server Function 에러 메시지가 프로덕션에서 사라지는 이유 개발 환경에서는 "이미 사용 중인 아이디입니다" 같은 에러 메시지가 잘 뜨는데,프로덕션에 배포하면 갑자기 이런 메시지로 바뀐 경험이 있을 것이다.An error occurred in the Server Components render.The specific message is omitted in production builds to avoid leaking sensitive details.원인은 Next.js의 의도적인 보안 정책이다.왜 이런 일이 생기나Next.js의 Server Function('use server')은 이름 그대로 서버에서 실행되는 함수다.클라이언트에서 호출하면 내부적으로 HTTP 요청을 만들어 서버에서 실행한다.'use server'export async function creat..
서버가 호출하는 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의 ..

반응형