Next.js 환경 변수 설정 및 보안 방법

Next.js에서 환경변수를 설정하고 보안을 위한 설정 방법과 Next js 클라이언트에서 환경변수 보안 설정 방법에 대해 알아보겠습니다.


소개

Next.js에서 환경 변수를 안전하게 관리하고 사용하는 방법에 대해 알아보겠습니다. 환경 변수는 API 키, 데이터베이스 접속 정보와 같은 민감한 정보를 관리하는 데 필수적입니다.

그리고 환경 변수를 사용할 때 React(Tanstack) Query와 같이 클라이언트 사이드에서도 접근 가능한 라이브러리를 사용할 때 주의해야 합니다. 이 글에서는 Next.js의 환경 변수 시스템을 사용하는 방법과 보안을 위한 모범 사례에 대해 알아보겠습니다.

version

  • Next.js: 14 이상 app router

목차

  1. 환경 변수 기본 설정
  2. 환경 변수 종류와 차이점
  3. 개발 환경과 프로덕션 환경 설정 분리
  4. 보안을 위한 모범 사례

1. 환경 변수 기본 설정

Next.js에서 환경 변수를 설정하는 기본적인 방법은 프로젝트 루트에 .env 파일을 생성하는 것입니다.

.env
# .env
DATABASE_URL="mongodb://localhost:27017/myapp"
API_KEY="your-api-key"

위 사용 방법 처럼 .env 파일에 환경 변수를 설정하면 process.env 객체를 통해 접근할 수 있습니다:

app/page.tsx
// app/page.tsx
export default function Home() {
  console.log(process.env.DATABASE_URL);
  console.log(process.env.API_KEY);
 
  return <div>Home</div>;
}
Next.js는 'use client'를 사용하지 않는 이상 기본적으로 서버에서 실행됩니다.

2. 환경 변수 종류와 차이점

Next.js는 다음과 같은 환경 변수 접두사를 제공합니다.

  • NEXT_PUBLIC_: 클라이언트 사이드에서 접근 가능
  • 접두사 없음: 서버 사이드에서만 접근 가능
app/page.tsx
// 클라이언트에서 접근 가능
console.log(process.env.NEXT_PUBLIC_API_URL);
 
// 서버에서만 접근 가능
console.log(process.env.DATABASE_URL);
.env
# .env
NEXT_PUBLIC_API_URL="https://api.example.com" # 클라이언트에서 접근 가능
DATABASE_URL="mongodb://localhost:27017/myapp" # 서버에서만 접근 가능

클라이언트에서 사용시 반드시 상단에 "use client"를 사용해야 합니다.

'use client';
import { useQuery } from 'react-query';
 
export default function Home() {
  const { data, isLoading } = useQuery('data', async () => {
    const response = await fetch(process.env.NEXT_PUBLIC_API_URL);
    return response.json();
  });
 
  if (isLoading) return <div>Loading...</div>;
 
  return <div>{data}</div>;
}

참고: NEXT_PUBLIC_ 접두사를 사용하면 클라이언트 사이드에서 접근 가능한 환경 변수를 설정할 수 있습니다.

만약 NEXT_PUBLIC_ 접두사를 사용하지 않으면 서버 사이드에서만 접근 가능하고 클라이언트 사이드에서는 접근할 수 없습니다. 빌드시 에러가 발생합니다.

NEXT_PUBLIC_ 사용해야 한다면 반드시 노출되어도 괜찮은 정보만 사용해야 합니다.

환경 변수를 클라이언트 사이드에서 사용할 때는 주의해야 합니다. 민감한 정보는 서버 사이드에서만 사용하세요.

3. 개발 환경과 프로덕션 환경 설정 분리

Next.js에서는 .env.development, .env.production 파일을 사용하여 개발 환경과 프로덕션 환경에 따라 다른 환경 변수를 설정할 수 있습니다.

  • .env.development: 개발 환경
  • .env.production: 프로덕션 환경
  • .env.test: 테스트 환경
.env.development
# .env.development
DATABASE_URL="mongodb://localhost:270
.env.production
# .env.production
DATABASE_URL="mongodb://production.com"

위 두 파일은 각각 개발 환경과 프로덕션 환경에서 사용됩니다. 개발 환경에서는 로컬 데이터베이스를 사용하고, 프로덕션 환경에서는 실제 데이터베이스를 사용할 수 있습니다.

Next.js는 NODE_ENV 환경 변수를 사용하여 환경을 구분합니다. NODE_ENV=development일 때는 .env.development 파일을 사용하고, NODE_ENV=production일 때는 .env.production 파일을 사용합니다.

다음은 개발 환경에서는 npm run dev 명령어로 실행하고, 프로덕션 환경에서는 npm run build && npm start 명령어로 실행합니다:

npm run dev # NODE_ENV=development
 
npm run build && npm start # NODE_ENV=production

위 방법을 사용하여 각 환경별로 다른 환경 변수를 설정할 수 있습니다.

.env 하나의 파일을 사용하는 것보다 .env.development, .env.production 환경별로 파일을 사용하는 것이 더 효율적입니다.

4. 보안을 위한 모범 사례

편의를 위해 React Query나 axios등 클라이언트 라이브러리를 사용해서 클라이언트에서 데이터를 다룰때가 자주 있을 수 있습니다.

민감한 정보를 담은 환경 변수를 사용할때 next-fetch를 사용하여 서버에서 데이터를 가져올 수 있지만, 편의를 위한 React Query같은 클라이언트 라이브러리를 사용할 때는 next js에서 제공하는 api route, 즉 Route Handler를 사용하여 서버에서 데이터를 가져오는 것이 좋습니다.

`Next js 공식문서 - route-handlers`

route handler는 GET, POST, PUT, DELETE 등의 HTTP 메서드를 사용하여 서버에서 데이터를 가져오는 방법입니다. 이 방법을 사용하면 환경 변수를 노출하지 않고 데이터를 가져올 수 있습니다.

우선 route handler를 사용하여 서버에서 데이터를 가져오는 방법을 알아보겠습니다.

app/api/user/route.ts
// app/api/user/route.ts
export async function GET() {
  const res = await fetch('https://data.mongodb-api.com/...', {
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
  });
  const data = await res.json();
 
  return Response.json({ data });
}

위 코드는 route handler를 사용하여 서버에서 데이터를 가져오는 예제입니다. 클라이언트에서는 useQuery를 사용하여 서버에서 데이터를 가져올 수 있습니다.

app/page.tsx
// app/page.tsx
'use client'; // 클라이언트의 예시
import { useQuery } from 'react-query';
 
export default function Home() {
  const { data, isLoading } = useQuery({
    queryKey: 'user',
    queryFn: async () => {
      const response = await fetch('/api/user');
      return response.json();
    },
  });
 
  //... 생략
}

위 코드처럼 서버 자체에서 next-fetch를 사용하지 않고, React-query 같은 사용성을 위한 라이브러리를 사용할 때는 route handler를 사용하여 환경 변수를 노출하지 않고 데이터를 가져올 수 있습니다.

주의사항 정리

  1. 클라이언트에서 환경 변수를 사용할 때는 NEXT_PUBLIC_ 접두사를 사용하세요.
  2. 민감한 정보는 서버 사이드에서만 사용하세요.
  3. 보안이 필요한 환경 변수를 클라이언트에서 사용할 때는 route handler를 사용하여 데이터를 가져오세요.

결론

Next.js의 환경 변수 시스템을 올바르게 사용하면 애플리케이션의 설정을 안전하고 효율적으로 관리할 수 있습니다. 환경별로 적절한 설정을 사용하고, 보안 모범 사례를 따르는 것이 중요합니다.

참고 자료

`Next.js 공식문서 - 환경 변수`

관련 태그