아, 이거 진짜 많은 분들이 처음 겪는 고민거리예요.
솔직히 말씀드리자면, 질문자님 말씀처럼 이 정도 규모에서는 JWT를 쓰면 개발 시간 대비 체감되는 복잡도가 엄청 높을 수 있어요.
그래서 저는 결론부터 말씀드리자면, 일단은 API 키 기반으로 시작하시되, 나중에 "이 친구들은 친구가 아니라, 역할이 다른 독립적인 사용자 그룹이야"라는 느낌이 들 때 JWT로 업그레이드하는 게 제일 마음 편하고 효율적인 경로라고 생각합니다.
하지만 '어떤 기준'으로 이 둘을 선택해야 할지 막막하실 테니까, 제가 조건별로 좀 더 깊게 풀어서 설명드릴게요.
우선, 인증 방식 선택에 앞서 딱 하나만 짚고 넘어갈게요.
가장 중요한 건 '이 인증이 누가 쓰는지'에 대한 정의가 먼저라는 거예요.
이게 단순한 '내 테스트용'인지, 아니면 '친구 A는 데이터 조회만 하고, 친구 B는 데이터 생성도 해야 하는' 식으로 역할 구분이 필요한지가 핵심 분기점이에요.
--- [1.
API 키 (API Key) 방식의 경우] 이건 가장 심플하고 직관적이에요.
키를 발급받고, 요청 헤더(Authorization 헤더 등)에 그 키를 넣어서 보내는 방식이죠.
장점 (이런 경우에 최고예요): * 극단적인 단순성: 로직 자체가 "이 키가 우리 DB에 등록된 키 리스트에 있나?
-> 있으면 통과." 딱 이거 하나만 검사하면 돼요.
- 즉각적인 제어: 문제가 생겼을 때, 해당 키만 DB에서 삭제하거나 비활성화하면 되니, 취소(Revoke)가 정말 빠르고 명확해요.
- 머신 간 통신에 최적: 만약 친구가 아닌, '내가 만든 스크립트'가 API를 호출하는 경우라면, 이 키 방식이 가장 적합해요.
호출 주체가 기계(Machine)이기 때문이죠.
단점 (이런 경우엔 아쉬워요): * 권한(Permission) 관리가 어려움: 단순히 키가 유효한지 여부만 알 수 있어요.
"이 키는 조회만 할 수 있어", "이 키는 생성만 할 수 있어" 같은 **세부 권한(Scope)**을 강하게 붙이려면, 키 자체에 'Scope' 필드를 추가로 관리해야 해서 복잡도가 올라가요.
- 사용자 식별의 모호함: 키를 가지고 왔을 때, 그 키가 'A라는 친구의 계정'인지, 아니면 '내가 임시로 만든 테스트 계정'인지에 대한 맥락을 키만으로는 파악하기 어려워요.
이런 분께 추천: * '나만 쓰는' 혹은 '스크립트만 돌리는' 테스트 환경. * 최대한 빠르게 작동하는 최소한의 기능만 구현하고 싶을 때. * 모든 사용자가 사실상 '같은 권한 그룹'일 때. --- [2.
JWT (JSON Web Token) 방식의 경우] JWT는 본질적으로 '신뢰할 수 있는 정보 덩어리'를 담는 전자 여권 같은 거예요.
사용자가 로그인(또는 인증)에 성공하면, 서버가 '너는 누구고(User ID), 어떤 권한을 가졌으며(Roles/Scopes), 언제까지 유효해(Expiry)'라는 정보가 담긴 토큰을 발급해줘요.
장점 (이런 경우에 강력해요): * 정보의 풍부함 (Claims): 토큰 자체에 user_id, role: admin, scope: read_write 같은 정보(클레임)를 담을 수 있어요.
이 정보 덕분에 매번 DB에 "이 사용자가 뭘 할 수 있는지" 물어볼 필요 없이, 토큰만 보고 "아, 이 사용자는 관리자니까 뭘 해도 돼" 처럼 바로 판단할 수 있어요.
- Stateless(무상태성): 서버가 사용자의 세션 정보를 매번 메모리에 저장할 필요가 없어요.
토큰 자체에 모든 정보가 담겨있기 때문에, 서버를 여러 대 늘려도(Scale Out) 세션 관리가 훨씬 용이해요.
- 표준화: 업계 표준에 가장 가깝고, 나중에 이 서버를 다른 서비스와 연동할 때 가장 범용적으로 쓰기 좋아요.
단점 (이런 경우엔 부담스러워요): * 초기 구현 복잡도: 비밀 키 관리, 토큰 서명/검증 과정, 만료 시간(Expiry) 처리, 그리고 Refresh Token 처리(토큰이 만료되었을 때 새 토큰을 받는 과정)까지 신경 쓸 게 많아요.
- 정보의 신뢰성 문제: 토큰을 받은 클라이언트가 토큰을 위조하려고 시도할 수 있으므로, 서명(Signature) 검증 로직이 절대적으로 중요해요.
이걸 놓치면 보안 구멍이 생겨요.
이런 분께 추천: * 실제 '사용자'의 개념이 생길 때. (친구 A는 관리자, 친구 B는 일반 사용자 등 역할 분리가 필요할 때).
- 나중에 트래픽이 늘어나서 서버를 여러 대 돌릴 계획이 생길 때. --- [3.
질문자님께 드리는 현실적인 하이브리드 추천 경로] 질문자님의 상황(소규모, 개인 프로젝트, 친구 몇 명)을 종합해 볼 때, 저는 **'API 키를 사용하되, 키와 함께 간단한 'Owner ID'를 매핑하는 방식'**을 추천합니다.
이건 JWT의 '사용자 식별' 개념만 차용하고, JWT의 복잡한 '토큰 생성/검증' 로직은 완전히 생략하는 절충안이에요.
구현 방법 예시: 1.
DB 설계: (api_key: VARCHAR, owner_id: INT, owner_name: VARCHAR, scope: VARCHAR) 와 같이 키를 저장하되, 키와 함께 이 키의 '소유자(Owner)' 정보를 명시적으로 저장하세요.
인증 과정: 사용자가 API 호출 시 키를 보내면, 서버는 DB에서 키를 찾습니다.
3.
검증 단계: 키가 유효한지 확인하는 것 외에, "이 키는 'User 123'이 소유한 것이고, 이 User 123은 '읽기 전용' 권한을 가졌어." 라는 정보를 함께 읽어와서 사용하세요.
이 방식의 장점: * JWT처럼 '세션'을 관리할 필요 없이, 키가 곧 사용자를 대표하는 식별자가 됩니다.
- 권한도 키 레벨에서 관리할 수 있어서, 필요한 경우에만 'Scope'를 부여해줄 수 있어요.
- JWT의 모든 복잡성(Refresh Token, 만료 로직 등)을 피할 수 있어요.
--- [마지막으로 꼭 기억해야 할 실무 팁 (주의점)] 이건 인증 방식과 별개로, 소규모 프로젝트에서 제일 많이 실수하는 부분이라 꼭 짚어드릴게요.
1.
키를 절대 URL 파라미터로 받지 마세요. * GET /api/data?key=SECRET_KEY 이런 식으로 요청 파라미터에 넣으면, 서버 로그나 브라우저 히스토리 등에 키가 그대로 남게 돼요.
- 무조건 HTTP Header (예:
Authorization 헤더)를 사용해야 합니다. 2.
Rate Limiting은 무조건 넣으세요. * 친구들이 쓰더라도, 나중에 한 명이 실수로 무한 루프를 돌리거나, 혹은 나도 모르게 테스트 코드가 무한 호출을 할 수 있어요.
- IP 주소나 API 키 단위로 "분당 최대 100번까지만 허용" 같은 제한(Rate Limiting)을 걸어두는 것만으로도 서버 안정성이 몇 단계 올라갑니다.
(이건 인증 로직과는 별개로, 인프라 레벨에서 처리하는 게 좋아요.) 3.
비밀 키(Secret) 관리에 신경 쓰세요. * 만약 JWT를 쓰기로 결정했다면, 서버가 사용하는 비밀 키(Secret Key)를 절대 코드에 하드코딩 하지 마세요.
- 반드시 환경 변수(
process.env.JWT_SECRET)를 통해 주입받아야 합니다.
결론적으로 다시 정리하자면, * 초보적 테스트 & 단순 API: API Key (Owner ID 매핑 추천) * 역할 구분이 중요해지기 시작할 때: JWT (하지만 신중하게 도입) 이렇게 단계적으로 접근하시는 게 시간과 노력 낭비를 막는 최고의 방법일 거예요.
너무 깊게 생각하실 필요는 없고, 일단 가장 간단한 구조로 API 키를 걸어보시고, "어?
이 친구는 다른 권한이 필요한데, 이 키로는 안 되겠네?" 라는 지점에서 고민을 다시 시작하시면 돼요.
제가 드린 답변이 조금 길긴 한데, 이 정도 깊이가 지금 질문자님께 가장 실질적인 도움이 되었으면 좋겠습니다.