팀 생성 여부 조회 시 URI 형식
내 질문
- URI에서 특히 filter 여러 개를 설정할 때 %의 역할이 뭐야? 예를 들면 https://www.kurly.com/collection-groups/market-best?page=1&collection=market-best-logic&filters=category%3A910%2C911%2C912 여기서 category의 % 같은 거!
- 이것처럼 나는 /team/?member= 이런 식으로 member 안에 사용자가 선택하는 여러 명의 사람들의 id를 여러 개 넣고 싶으면 &을 써서 나열해야 돼? 아니면 저 category처럼 %를 써야 돼?
- 백엔드는 Spring으로 개발 중이야. 사용자가 사람들을 선택해서 버튼을 눌렀을 때 프론트에서 그 사람들의 memberId들을 URL에 넣어서 백으로 Get method로 요청을 보내면 내가 그 멤버들로 이루어진 팀이 이미 있는지 없는지 true, false를 알려주는 API를 구현하려고 해. 이때 URI를 어떤 형태로 구성할지 고민돼서 물어봤어.
GPT 답변
Spring 백엔드라면 가장 자연스러운 방식은 쿼리 파라미터로 여러 개의 memberId를 보내는 것이야.
아래 3가지 방식 중에서 선택하면 돼! 🚀
✅ 1. &memberId= 여러 개 (가장 직관적, Spring에서 자동 처리)
- Spring에서는 @RequestParam List<Long> memberId로 받을 수 있음.
- 장점: Spring이 자동으로 리스트로 변환해 줌.
🔹 Spring 컨트롤러 예시
✅ 2. ,로 나열하는 방식 (split() 필요)
- 백엔드에서 ,를 기준으로 split() 해서 리스트로 변환해야 함.
- 장점: URL이 짧고 깔끔함.
🔹 Spring 컨트롤러 예시
✅ 3. PathVariable로 배열 전달 (/로 구분)
- RESTful하게 보일 수 있지만, 일반적인 GET 요청에서 여러 개의 데이터를 다룰 땐 보통 QueryParam을 더 많이 씀.
- 장점: RESTful 스타일.
- 단점: 멤버 개수가 동적으로 변하는 경우 URI가 길어질 수 있음.
🔹 Spring 컨트롤러 예시
⚠️ 주의: Spring Boot 3.x 이상부터 @PathVariable List<Long>가 자동 변환되지 않을 수도 있음.
이럴 땐 @PathVariable String memberIds로 받고 split("/")을 사용해야 해.
💡 어떤 방식을 선택할까?
✅ Spring에서 자동 리스트 변환을 원하면 → 방법 1 (&memberId=101&memberId=102) 추천!
✅ URL을 더 깔끔하게 하고 싶다면 → 방법 2 (?memberId=101,102,103) 추천!
✅ RESTful하게 보이고 싶다면 → 방법 3 (/team/exists/101/102/103) 가능! (하지만 비추 😅)
👉 가장 많이 쓰는 방식은 1번이야!
Spring이 자동 변환해 주니까, 추가 처리 없이 깔끔하게 받을 수 있어. 🚀
/team/{team_id} 형태의 팀 정보 조회 API를 말하는 거구나.
이 API에서는 GET 요청이니까 Request Body를 안 쓰는 게 맞아!
💡 /team/{team_id}는 이렇게 설계하면 좋아!
✅ 1. 기본적인 RESTful 구조 유지
- 팀 ID를 경로 변수(PathVariable)로 사용하면 깔끔하고 RESTful한 API가 됨.
✅ 장점:
- URL이 직관적이고 RESTful함.
- Spring이 @PathVariable을 자동으로 매핑해줌.
- 팀 조회니까 GET 요청에서 Body 없이 처리하는 게 적절함!
✅ 2. 보안 고려 (JWT + 권한 체크)
- /team/{team_id}가 있으면 다른 사람이 내 팀 정보를 몰래 조회할 수 있는지가 문제야.
- @AuthenticationPrincipal을 사용해서 현재 로그인한 사용자가 해당 팀에 속해 있는지 검증해야 함.
✅ 이렇게 하면:
- 로그인한 사용자만 요청 가능!
- 자신이 속한 팀만 조회 가능!
- 권한이 없으면 403 Forbidden 반환!
✅ 3. URL ID 예측 가능성 방지 (UUID 고려)
- 만약 team_id가 단순 숫자라면,
plaintext복사편집GET /team/1 GET /team/2
- 이를 방지하려면 UUID 사용 고려:
plaintext복사편집GET /team/d0f3e8d6-9c4e-4e48-bdfb-2b65ef7a4c20java복사편집@GetMapping("/team/{teamId}") public ResponseEntity<TeamDto> getTeam(@PathVariable UUID teamId, @AuthenticationPrincipal User user) { if (!teamService.userHasAccess(user, teamId)) { return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); } return ResponseEntity.ok(teamService.getTeam(teamId)); }
✅ UUID를 쓰면:
- 예측 불가능한 팀 ID → 공격자가 무작위로 ID를 요청해도 찾기 어려움.
- 보안 강화!
🔴 🚨 GET 요청에 Request Body를 쓰면 안 되는 이유!
- HTTP 표준 상 GET 요청은 Request Body를 포함하지 않는 것이 원칙!
- Spring에서도 기본적으로 GET 요청의 Body를 무시함.
- GET 요청에서 데이터를 보내려면 PathVariable 또는 Query Parameter 사용이 맞는 방식.
✨ 최종 정리
- GET 요청에서 Body는 쓰지 않는다!
- URI는 /team/{team_id} 형태가 RESTful하고 깔끔함!
- 보안을 위해 JWT + 팀 접근 권한 체크 필수!
- ID Enumeration 방지를 위해 UUID 사용 고려 가능!
👉 이대로 가면 완벽한 팀 조회 API가 될 거야! 🚀
나의 말:
ChatGPT의 말:
맞아! URI에서는 일반적으로 소문자를 사용하는 것이 표준이야.
🔹 왜 URI에서 대문자를 잘 안 쓸까?
- 일관성과 가독성 유지
- 소문자를 쓰면 URL이 더 읽기 쉽고 깔끔함.
- 대부분의 REST API는 소문자와 -, _를 조합해서 사용함.
- 예)
sql복사편집❌ /Team/Exists?MemberId=101&MemberId=102 (비추천) ✅ /team/exists?memberId=101&memberId=102 (추천)
- 대소문자 구분 문제
- RFC 3986 (URI 표준) 에 따르면, 경로(path) 부분은 대소문자를 구별할 수도 있음!
- 일부 서버(Linux 기반)는 /team/exists와 /Team/Exists를 다르게 취급할 수도 있음.
- 반면, 도메인 이름은 대소문자를 구별하지 않음.
perl복사편집https://WWW.GOOGLE.COM == https://www.google.com (동일)swift복사편집/api/users ≠ /API/Users (다를 수 있음!)
- RESTful API 스타일 가이드
- REST API에서 리소스명(경로)은 소문자를 사용하는 것이 일반적.
- 보통 동사는 사용하지 않고 명사만 사용 (예: /team/exists → /team/check-existence 권장).
- 공백 대신 하이픈(-)을 선호 (_도 가능하지만 잘 안 씀).
- 예)
bash복사편집❌ /GetTeamInfo?MemberId=101 ✅ /team/info?memberId=101
🔹 쿼리 파라미터 (Query Parameter)에서는?
- 쿼리 파라미터도 보통 소문자로 씀.
- 하지만, 쿼리 파라미터는 일부 서버에서 대소문자 구별을 안 할 수도 있음.
- ?memberId=101 == ?MEMBERID=101 (서버 설정에 따라 다름).
- 하지만 소문자로 통일하는 것이 가독성과 일관성 면에서 더 좋음.
✅ 최적의 URI 스타일
✔ 경로(path)는 소문자만 사용
✔ 동사 대신 명사 사용 (exists 대신 check 고려 가능)
✔ 하이픈(-) 사용 가능 (/team-check 같은 형태 가능)
👉 결론: 소문자로 통일하는 것이 표준적이고 가독성이 좋음! 🚀
나의 말:
ChatGPT의 말:
좋은 질문이야! 쿼리 파라미터(memberId=101&memberId=102)에서도 소문자를 사용하는 것이 일관성 면에서 더 좋음.
🔹 Query Parameter 네이밍 스타일 가이드
RESTful API에서 쿼리 파라미터는 소문자와 하이픈(-) 또는 언더스코어(_)를 사용하는 것이 일반적이야.
✅ 1. camelCase vs snake_case vs kebab-case
스타일예시REST API에서 추천 여부camelCase | memberId=101 | 🚫 비추천 (URI는 보통 소문자로 통일) |
snake_case | member_id=101 | ⭕ 가능하지만 잘 안 씀 |
kebab-case | member-id=101 | ✅ 가장 RESTful한 스타일 |
🔹 그러면 memberId를 어떻게 바꾸는 게 좋을까?
1️⃣ member-id (권장)
✅ REST API 가이드에서 가장 추천하는 형식!
✔ kebab-case (- 사용) → RESTful한 URL 설계에서 가장 선호됨.
✔ URI에서도 하이픈(-)을 사용하기 때문에 일관성이 있음.
✔ 대부분의 웹 프레임워크(Swagger, OpenAPI)에서도 kebab-case를 선호함.
2️⃣ member_id (차선책)
⭕ 사용 가능하지만 잘 안 쓰임.
✔ snake_case는 JSON에서 자주 사용하지만, 쿼리 파라미터에서는 잘 안 씀.
✔ 일부 시스템(Python, PostgreSQL 등)에서는 snake_case를 선호하기도 함.
✔ 하지만 URL에서 _(언더스코어)는 잘 보이지 않아서 가독성이 떨어짐.
3️⃣ memberId (비추천)
🚫 쿼리 파라미터에서 camelCase는 비추천!
❌ 대부분의 RESTful API 스타일 가이드에서 camelCase 사용을 권장하지 않음.
❌ URI는 보통 소문자로만 구성되기 때문에, memberId처럼 대문자가 섞이면 일관성이 깨짐.
❌ JSON 응답에서는 camelCase를 많이 쓰지만, URI에서는 kebab-case(-)를 쓰는 게 더 일반적임.
🚀 최적의 URI 스타일
✔ 최종적으로 추천하는 형태
✔ 쿼리 파라미터도 소문자로 통일!
✔ kebab-case(- 사용) 유지!
✔ members=101,102처럼 여러 개의 값을 ,로 구분하는 것도 가능!
💡 결론
✔ 쿼리 파라미터에서도 kebab-case(- 사용)를 쓰는 것이 가장 RESTful함!
✔ URI 전체를 소문자로 유지하는 것이 가독성과 일관성 면에서 좋음.
✔ 여러 개의 멤버 ID를 전달할 때는 member-id=101&member-id=102 또는 members=101,102 사용 가능!
👉 즉, member-id 또는 members로 바꾸는 게 좋겠어! 🚀