들어가기 앞서, 클라이언트 환경변수는 모두 브라우저에 노출된다는 사실을 인지해야한다.
필자는 현재 Next.js + Supabse를 활용해 풀스택(?) 프로젝트를 개발하는 상황이다.
이 때, 프로젝트에서는 클라이언트 환경변수(NEXT_PUBLIC)에 Supabase API 요청을 위한 보안 키인 anon 키 값을 저장한다.
이에, 클라이언트측에서 직접 API 요청을 보내고 비즈니스 로직 또한 브라우저에 노출된다.
그러던 중, 클라이언트 환경변수에 anon키를 저장하면 브라우저에 노출될텐데 이런 경우네는 어떤 보안 위협성이 있는 지 생각했다.
결론부터 말하면 anon키가 클라이언트에게 노출됨으로써 데이터접근 권한 및 DOS 공격과 관련된 보안 위협은 증가하지 않는다.
다양한 예시 상황으로 보안 위협을 가정해보았다.
1. 클라이언트 환경변수에 anon 키 등록 + Supabase에 직접 API 요청
2. Next.js API 라우터를 통해 클라이언트 서버 분리 + 서버 환경변수에 anon 키 등록
1번 상황에서는 직접 API 요청을 하기 때문에 비즈니스 로직이 모두 노출된다.
2번 상황에서는 클라이언트와 서버가 분리되어있기 때문에 비즈니스 로직이 노출되지 않는다.
1번 2번 상황 모두 데이터접근 권한 및 DOS 공격에 대한 보안이 취약하다.
즉, anon키 노출로 인해 데이터접근 권한 및 DOS 공격과 관련된 보안 위협은 증가하지 않는다.
따라서, 데이터접근 권한 및 DOS 공격과 관련된 보안 위협은 Supabase RLS 설정과 서버측 Rate Limiting을 통 보안 위협을 예방해야한다.
============GPT 4.0 답변
정확합니다! anon 키를 숨기는 것, RLS 설정, 그리고 Rate Limiting은 각각 다른 보안 목적을 가지고 있으며, 각각의 역할이 다릅니다. 결국, 모든 보안 문제를 한 가지 방법으로 해결할 수는 없기 때문에, 각각의 보안 계층을 적절히 활용해야 합니다.
다시 정리하자면:
1. 데이터 접근 권한 문제: RLS (Row-Level Security)로 해결
- 데이터 접근 제어와 보안 문제는 RLS를 통해 해결해야 합니다.
- RLS의 역할:
- 데이터베이스 수준에서 요청을 제한.
- 특정 사용자가 자신의 데이터 또는 허용된 데이터만 접근할 수 있도록 강제.
- 결론: RLS는 데이터 접근에 대한 보안을 책임지며, 클라이언트가 요청을 조작하더라도 잘못된 데이터를 반환하지 않습니다.
2. DoS 공격 문제: Rate Limiting으로 해결
- DoS(Denial of Service) 공격은 API 엔드포인트에 대량의 요청을 보내 서비스 가용성을 방해하는 행위입니다.
- Rate Limiting의 역할:
- 클라이언트당 요청 횟수를 제한하여 서버 리소스 남용 방지.
- 악의적인 IP나 과도한 요청을 차단.
- 결론: DoS 공격을 방지하려면 Rate Limiting을 설정하고, API 요청 수를 제어해야 합니다.
3. anon 키를 숨기는 이유: 클라이언트-서버 역할 분리
- anon 키는 노출되더라도 RLS가 제대로 설정되어 있으면 보안 문제가 발생하지 않습니다.
- 그러나 anon 키를 숨기는 이유는 다른 보안 목적이 있습니다:
- 클라이언트와 데이터베이스 간의 직접 통신을 방지하여 추가적인 보안 계층 확보.
- 서버에서 추가적인 검증(예: 비즈니스 로직, 요청 필터링)을 수행할 수 있는 환경 제공.
- 데이터베이스와의 직접 연결을 차단해 API 사용 제어(요청 로깅, 분석 등) 가능.
- 결론: anon 키를 숨기는 것은 데이터베이스와 클라이언트의 직접 연결을 방지하고, 보안 관리의 중앙화를 위해 필요합니다.
4. API 라우트를 통한 보안 계층 설계
API 라우트를 활용하면, 다음과 같은 방식으로 각각의 보안 문제를 해결할 수 있습니다:
a. RLS + 서버 검증 (데이터 접근 보안)
- 클라이언트는 Next.js API 라우트를 통해 데이터를 요청합니다.
- RLS는 데이터베이스 수준에서 접근을 제어하고, 서버는 요청 데이터를 검증합니다.
// app/api/data/route.js
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_ANON_KEY);
export async function POST(request) {
const { userId } = await request.json();
// RLS에 의해 데이터 접근 제한
const { data, error } = await supabase
.from('your_table')
.select('*')
.eq('user_id', userId);
if (error) {
return new Response(JSON.stringify({ error: error.message }), { status: 400 });
}
return new Response(JSON.stringify(data), { status: 200 });
}
b. Rate Limiting (DoS 공격 방지)
- 클라이언트당 요청 속도를 제한하여 서버 리소스를 보호합니다.
- Next.js API 라우트 또는 Nginx 같은 프록시 서버에서 설정 가능합니다.
Next.js API 라우트에서 Rate Limiting
import rateLimit from 'express-rate-limit';
// 요청 제한 설정: 1분에 100건 허용
const limiter = rateLimit({
windowMs: 60 * 1000, // 1분
max: 100, // 요청 100건 허용
message: 'Too many requests, please try again later.',
});
export default function handler(req, res) {
limiter(req, res, () => {
if (req.method === 'POST') {
// POST 요청 처리
res.status(200).json({ message: 'Request accepted' });
} else {
res.status(405).end('Method Not Allowed');
}
});
}
Nginx에서 Rate Limiting 설정
http {
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://localhost:3000;
}
}
}
5. 최종 결론
- RLS는 데이터 접근 제어에 대한 보안 솔루션입니다.
- 사용자가 자신의 데이터만 접근하도록 보장.
- 클라이언트가 요청을 조작해도 데이터가 노출되지 않음.
- Rate Limiting은 DoS 공격에 대한 보안 솔루션입니다.
- 클라이언트의 요청 속도를 제한하여 서버를 보호.
- 악의적인 요청을 차단하고 리소스 낭비 방지.
- API 라우트와 anon 키 숨기기는 보안을 한층 강화하기 위한 추가적인 계층입니다.
- 서버에서 비즈니스 로직, 요청 검증, 로깅, 제한 등을 처리할 수 있습니다.
따라서, RLS는 데이터 보호, Rate Limiting은 DoS 방지, API 라우트는 역할 분리와 추가 검증이라는 고유한 역할이 있으므로, 이 세 가지를 조합하는 것이 이상적인 보안 설계입니다.
'프론트엔드 > Next.js' 카테고리의 다른 글
[Next.js] Next.js 환경에서 MUI integration 방법 + MUI 전역 스타일링 방법 (1) | 2024.12.03 |
---|---|
[Next.js] "use client"는 CSR 방식과 동일할까? (1) | 2024.12.02 |
[Next.js] Next.js에서 SVG를 컴포넌트처럼 사용하는 방법 (0) | 2024.12.01 |
[Next.js] Next.js + Styled-components 적용하기 (0) | 2024.11.30 |
[Next.js] 서버 컴포넌트 VS 클라이언트 컴포넌트 (0) | 2024.08.14 |