스토리텔링 형식으로 업데이트되었습니다! 실무 사례와 함께 더 쉽게 이해할 수 있어요.
이미지 로딩 중...
AI Generated
2025. 11. 25. · 21 Views
RESTful URL 설계 베스트 프랙티스
RESTful API를 설계할 때 가장 중요한 URL 설계 원칙을 알아봅니다. 리소스 중심 설계부터 버전 관리까지, 초급 개발자도 쉽게 따라할 수 있는 실무 가이드입니다.
목차
1. 리소스_중심의_URL_구조
여러분이 쇼핑몰 API를 만들 때 이런 고민을 해본 적 있나요? "상품 목록을 가져오는 URL은 /getProducts로 할까, /products로 할까?" 이런 고민은 실제 개발 현장에서 매일 일어납니다.
URL을 어떻게 설계하느냐에 따라 API가 직관적이 될 수도 있고, 나중에 유지보수가 어려워질 수도 있습니다. 바로 이럴 때 필요한 것이 리소스 중심의 URL 설계입니다.
리소스란 우리가 다루는 "데이터"나 "대상"을 말하는데, 이것을 URL의 중심에 놓으면 누구나 이해하기 쉬운 API가 됩니다.
간단히 말해서, 리소스 중심 URL은 "무엇을" 다루는지를 URL에 명확히 표현하는 방식입니다. 이 방식이 필요한 이유는 API를 사용하는 다른 개발자들이 URL만 보고도 "아, 이 API는 사용자 정보를 다루는구나"라고 바로 이해할 수 있기 때문입니다.
예를 들어, 회원 관리 시스템에서 /users라는 URL을 보면 사용자 관련 기능이라는 것을 누구나 알 수 있습니다. 전통적인 방법에서는 /getUserList, /createNewUser, /deleteUserById처럼 동작을 URL에 포함시켰습니다.
하지만 리소스 중심에서는 /users 하나로 통일하고, HTTP 메서드(GET, POST, DELETE)로 동작을 구분합니다. 핵심 특징은 첫째, URL은 명사(리소스)만 포함합니다.
둘째, 동작은 HTTP 메서드로 표현합니다. 셋째, 일관된 패턴으로 예측 가능합니다.
다음 코드를 살펴봅시다.
// 잘못된 방식 - 동작을 URL에 포함
// GET /getUsers
// POST /createUser
// DELETE /removeUser/123
// 올바른 방식 - 리소스 중심 설계
// GET /users - 모든 사용자 조회
// GET /users/123 - 특정 사용자 조회
// POST /users - 새 사용자 생성
// PUT /users/123 - 사용자 정보 수정
// DELETE /users/123 - 사용자 삭제
// Express.js 라우터 예시
router.get('/users', getAllUsers);
router.get('/users/:id', getUserById);
router.post('/users', createUser);
router.put('/users/:id', updateUser);
router.delete('/users/:id', deleteUser);
도입 스토리 신입 개발자 민수는 첫 API를 설계하면서 /getAllProducts, /insertProduct, /modifyProduct 같은 URL을 만들었다. 선배가 코드를 보더니 "REST 스타일로 바꿔볼까?"라고 제안했다.
리소스 중심 URL이란? 리소스 중심 URL은 API가 다루는 "대상"을 URL의 핵심으로 삼는 설계 방식입니다. 마치 도서관에서 책을 찾을 때 "소설 코너", "과학 코너"처럼 대상을 기준으로 정리하는 것과 같습니다.
기존 방식의 문제점: - 일관성 부족: /getUser, /fetchProduct, /retrieveOrder처럼 같은 조회인데 다른 동사 사용 - URL 폭발: 동작마다 새 URL이 필요해서 수십 개의 엔드포인트 발생 - 예측 불가: 새 기능의 URL을 매번 외워야 함 리소스 중심의 장점: - 직관적: URL만 보면 무슨 데이터인지 바로 앎 - 일관성: 모든 리소스가 같은 패턴을 따름 - 확장성: 새 리소스 추가가 쉬움 실제 동작 원리 1단계: 클라이언트가 /users에 GET 요청을 보냅니다. 2단계: 서버는 HTTP 메서드가 GET임을 확인하고 조회 로직을 실행합니다.
3단계: 사용자 목록이 JSON 형태로 반환됩니다. 실무 활용 예시 쇼핑몰 API를 설계한다면 /products, /orders, /customers 세 가지 리소스를 정의하고, 각각에 CRUD 작업을 HTTP 메서드로 연결합니다.
주의사항 URL에 동사를 넣고 싶은 유혹이 있지만, 대부분의 경우 HTTP 메서드로 충분히 표현 가능합니다.
실전 팁
💡 URL에 get, create, delete 같은 동사가 보이면 리소스 중심으로 리팩토링하세요
💡 하나의 리소스에 하나의 URL을 원칙으로 삼으세요
2. 명사형_리소스_이름_사용
API URL을 보다가 /doPayment, /processOrder 같은 주소를 본 적 있나요? 이런 URL은 무엇을 하는지는 알겠는데, 정확히 어떤 데이터를 다루는지 헷갈립니다.
문제는 동사형 URL이 API의 구조를 복잡하게 만든다는 것입니다. 결제를 조회하려면 /getPayment?
/viewPayment? /fetchPayment?
어떤 걸 써야 할지 매번 고민해야 합니다. 명사형 리소스 이름을 사용하면 이 문제가 깔끔하게 해결됩니다.
/payments 하나면 결제와 관련된 모든 작업을 표현할 수 있습니다.
명사형 리소스란 URL에 "대상"의 이름만 사용하고, "행동"은 HTTP 메서드에 맡기는 방식입니다. 이 방식이 중요한 이유는 팀 전체가 같은 규칙을 따를 수 있기 때문입니다.
"주문은 /orders야"라고 정하면, 조회든 생성이든 수정이든 모두 이 URL을 기준으로 합니다. 새로 합류한 팀원도 패턴만 이해하면 바로 적응할 수 있습니다.
동사형 URL(/createOrder, /cancelOrder)을 쓰면 기능이 추가될 때마다 새 URL을 만들어야 합니다. 하지만 명사형(/orders)을 쓰면 HTTP 메서드만 바꾸면 됩니다.
핵심은 복수형 명사를 사용하는 것입니다. /user보다 /users가 컬렉션(목록)을 다룬다는 것을 더 명확히 표현합니다.
다음 코드를 살펴봅시다.
// 잘못된 방식 - 동사형 URL
// POST /createArticle
// GET /getArticleList
// PUT /updateArticle/123
// DELETE /removeArticle/123
// 올바른 방식 - 명사형 복수 URL
// POST /articles - 새 글 작성
// GET /articles - 글 목록 조회
// GET /articles/123 - 특정 글 조회
// PUT /articles/123 - 글 수정
// DELETE /articles/123 - 글 삭제
// 실제 Express 라우터 구현
const express = require('express');
const router = express.Router();
router.route('/articles')
.get(listArticles) // 목록 조회
.post(createArticle); // 새로 생성
router.route('/articles/:id')
.get(getArticle) // 단건 조회
.put(updateArticle) // 수정
.delete(deleteArticle); // 삭제
도입 스토리 개발팀에서 API 문서를 정리하던 중 /getUserInfo, /fetchUserData, /retrieveUserProfile 세 개의 URL이 모두 같은 기능을 한다는 것을 발견했다. 누가 만들었는지에 따라 다른 이름이 붙어있었던 것이다.
명사형 리소스란? 명사형 리소스는 URL에 "무엇을"만 적고 "어떻게"는 HTTP 메서드에 맡기는 규칙입니다. 마치 식당 메뉴판에 "치킨"이라고만 적고, 손님이 "주세요(주문)", "취소해주세요(취소)"라고 말하는 것과 같습니다.
동사형 URL의 문제점: - 중복: /createUser, /addUser, /registerUser가 모두 같은 기능 - 혼란: 수정이 /editUser인지 /updateUser인지 /modifyUser인지 헷갈림 - 문서화 어려움: 수십 개의 URL을 일일이 설명해야 함 명사형 URL의 장점: - 단순함: 리소스당 하나의 URL만 기억하면 됨 - 예측 가능: /products가 있으면 /categories도 같은 패턴일 것 - 표준화: 업계 표준을 따르므로 외부 개발자도 이해하기 쉬움 실제 동작 원리 1단계: /articles라는 URL이 정해지면 이것이 "글" 리소스의 대표 주소가 됩니다. 2단계: 클라이언트는 GET, POST, PUT, DELETE 중 원하는 메서드를 선택합니다.
3단계: 서버는 메서드에 따라 조회, 생성, 수정, 삭제 로직을 실행합니다. 실무 활용 예시 블로그 서비스라면 /posts(글), /comments(댓글), /tags(태그) 세 가지 명사형 리소스로 전체 API를 구성할 수 있습니다.
주의사항 단수형(/user)보다 복수형(/users)을 사용하세요. 컬렉션을 다룬다는 것이 더 명확해집니다.
실전 팁
💡 URL을 정할 때 "이것은 무엇인가?"라고 질문하면 명사가 나옵니다
💡 복수형을 기본으로 하되, /users/123처럼 ID가 붙으면 단일 항목을 의미합니다
3. 계층_구조와_관계_표현
블로그 API를 만들 때 "특정 글의 댓글"을 어떻게 표현해야 할까요? /comments?postId=123?
아니면 /posts/123/comments? 데이터 간의 관계를 URL로 표현하지 않으면, API 사용자는 매번 문서를 찾아봐야 합니다.
"이 댓글이 어느 글에 속한 건지" URL만 보고는 알 수 없기 때문입니다. 계층 구조를 사용하면 /posts/123/comments라는 URL만 봐도 "123번 글의 댓글들"이라는 것을 바로 알 수 있습니다.
계층 구조란 데이터 간의 소속 관계를 슬래시(/)로 표현하는 방식입니다. 이 방식이 필요한 이유는 실제 데이터가 계층적으로 연결되어 있기 때문입니다.
사용자가 주문을 하고, 주문에는 상품들이 포함됩니다. /users/123/orders/456/items처럼 URL이 이 관계를 그대로 보여줍니다.
기존에는 /getOrderItems?userId=123&orderId=456처럼 쿼리 파라미터로 관계를 표현했습니다. 하지만 계층 구조를 쓰면 URL 경로 자체가 관계를 설명합니다.
핵심 특징은 부모-자식 관계가 명확히 드러나고, URL만으로 데이터 구조를 이해할 수 있으며, 접근 권한 관리도 쉬워진다는 것입니다.
다음 코드를 살펴봅시다.
// 계층 구조 URL 예시
// /users/123 - 123번 사용자
// /users/123/posts - 123번 사용자의 글 목록
// /users/123/posts/456 - 123번 사용자의 456번 글
// /users/123/posts/456/comments - 456번 글의 댓글들
// Express 라우터 구현
const router = express.Router();
// 사용자의 주문 목록
router.get('/users/:userId/orders', async (req, res) => {
const { userId } = req.params;
const orders = await Order.find({ userId });
res.json(orders);
});
// 특정 주문의 상품 목록
router.get('/users/:userId/orders/:orderId/items', async (req, res) => {
const { userId, orderId } = req.params;
const items = await OrderItem.find({ orderId });
res.json(items);
});
// 새 댓글 작성 (특정 글에)
router.post('/posts/:postId/comments', async (req, res) => {
const { postId } = req.params;
const comment = await Comment.create({ ...req.body, postId });
res.status(201).json(comment);
});
도입 스토리 쇼핑몰 API를 설계하던 개발자가 "사용자의 장바구니 상품"을 표현하려고 했다. /cartItems?userId=123로 할까 고민하다가, /users/123/cart/items가 훨씬 직관적이라는 것을 깨달았다.
계층 구조란? 계층 구조는 데이터의 소속 관계를 URL 경로로 표현하는 방식입니다. 마치 컴퓨터의 폴더 구조(문서/업무/보고서/월간보고서.docx)처럼, 큰 것에서 작은 것으로 좁혀가는 구조입니다.
평면적 URL의 문제점: - 관계 불명확: /comments/789가 어느 글의 댓글인지 URL만으로 알 수 없음 - 쿼리 의존: 항상 ?postId=123 같은 파라미터가 필요 - 구조 파악 어려움: 전체 데이터 관계를 이해하기 힘듦 계층 구조의 장점: - 자기 설명적: URL이 데이터 관계를 설명함 - 직관적 탐색: 상위 경로를 잘라내면 부모 리소스에 접근 - 보안 용이: 경로 기반 권한 체크가 쉬움 실제 동작 원리 1단계: /users/123/orders로 요청이 들어옵니다. 2단계: 서버는 userId=123인 사용자의 주문만 필터링합니다.
3단계: 해당 사용자의 주문 목록만 반환됩니다. 실무 활용 예시 SNS 서비스에서 /users/kim/followers는 kim의 팔로워 목록, /users/kim/following은 kim이 팔로우하는 사람 목록을 반환합니다.
주의사항 계층이 3단계를 넘어가면(/a/1/b/2/c/3/d/4) 너무 복잡해집니다. 이런 경우 쿼리 파라미터를 병행하세요.
실전 팁
💡 계층은 2-3단계가 적당합니다. 너무 깊으면 URL이 복잡해져요
💡 상위 URL을 잘라내면 부모 리소스가 되도록 설계하세요
4. 쿼리_파라미터_활용법
상품 목록에서 "가격이 10000원 이하이고, 최신순으로 정렬된" 상품만 가져오려면 어떻게 해야 할까요? 매번 새 URL을 만들 순 없습니다.
필터링, 정렬, 페이징 같은 조건을 URL 경로에 넣으면 /products/cheap/newest/page1처럼 복잡해지고, 조합이 폭발적으로 늘어납니다. 쿼리 파라미터를 사용하면 /products?maxPrice=10000&sort=newest&page=1처럼 깔끔하게 조건을 추가할 수 있습니다.
쿼리 파라미터는 URL 뒤에 물음표(?)를 붙이고 조건을 나열하는 방식입니다. 이 방식이 필요한 이유는 같은 리소스에 대해 다양한 조건으로 조회해야 하는 경우가 많기 때문입니다.
상품 목록은 하나지만, 보는 방식(필터, 정렬, 페이지)은 수십 가지가 될 수 있습니다. 기존 URL 경로 방식은 조건 조합마다 새 경로가 필요했습니다.
하지만 쿼리 파라미터는 자유롭게 조합할 수 있어서, 클라이언트가 필요한 조건만 골라서 요청할 수 있습니다. 핵심 용도는 필터링(조건), 정렬(순서), 페이징(페이지), 검색(키워드)입니다.
다음 코드를 살펴봅시다.
// 쿼리 파라미터 활용 예시
// GET /products?category=electronics - 전자제품만
// GET /products?minPrice=1000&maxPrice=5000 - 가격 범위
// GET /products?sort=price&order=asc - 가격 오름차순
// GET /products?page=2&limit=20 - 2페이지, 20개씩
// GET /products?search=laptop - 검색어
// Express에서 쿼리 파라미터 처리
router.get('/products', async (req, res) => {
const {
category,
minPrice = 0,
maxPrice = Infinity,
sort = 'createdAt',
order = 'desc',
page = 1,
limit = 10,
search
} = req.query;
let query = Product.find();
// 필터링
if (category) query = query.where('category').equals(category);
if (minPrice) query = query.where('price').gte(minPrice);
if (maxPrice) query = query.where('price').lte(maxPrice);
if (search) query = query.where('name').regex(new RegExp(search, 'i'));
// 정렬 및 페이징
const skip = (page - 1) * limit;
const products = await query.sort({ [sort]: order }).skip(skip).limit(limit);
res.json(products);
});
도입 스토리 프론트엔드 개발자가 상품 목록 페이지를 만들면서 "카테고리별, 가격별, 정렬별로 필터가 필요해요"라고 요청했다. 백엔드 개발자는 수십 개의 URL을 만들 생각에 막막했지만, 쿼리 파라미터 하나로 모든 조합을 해결했다.
쿼리 파라미터란? 쿼리 파라미터는 URL 뒤에 붙는 옵션 설정입니다. 마치 커피를 주문할 때 "아메리카노요, 아이스로, 샷 추가해주세요"라고 기본 메뉴에 옵션을 덧붙이는 것과 같습니다.
경로로 조건을 표현할 때의 문제: - 조합 폭발: /products/cheap, /products/expensive, /products/newest... 끝이 없음 - 다중 조건: "싸면서 최신인" 상품은 어떤 경로로?
- 유연성 부족: 새 필터 추가 시 경로 구조 변경 필요 쿼리 파라미터의 장점: - 무한 조합: 필요한 조건만 골라서 조합 가능 - 선택적: 조건을 안 넣으면 기본값 적용 - 명확한 의미: key=value 형태로 조건이 명확함 실제 동작 원리 1단계: 클라이언트가 /products?category=shoes&sort=price를 요청합니다. 2단계: 서버는 query 객체에서 category와 sort를 추출합니다.
3단계: 신발 카테고리를 가격순으로 정렬해서 반환합니다. 실무 활용 예시 대시보드에서 /analytics?startDate=2024-01-01&endDate=2024-12-31&groupBy=month로 기간별 통계를 유연하게 조회합니다.
주의사항 쿼리 파라미터는 조회(GET)에 주로 사용합니다. 데이터 생성(POST)에는 본문(body)을 사용하세요.
실전 팁
💡 필터, 정렬, 페이징은 쿼리 파라미터의 대표적인 용도입니다
💡 기본값을 잘 설정해두면 파라미터 없이도 동작합니다
5. 버전_관리_전략
API를 운영하다 보면 기존 기능을 바꿔야 할 때가 옵니다. 그런데 이미 수천 개의 앱이 이 API를 사용하고 있다면?
갑자기 바꾸면 모든 앱이 동시에 오류를 냅니다. 이런 상황은 실제로 자주 발생합니다.
새 기능을 추가하거나, 응답 형식을 개선하거나, 오래된 기능을 제거해야 할 때마다 기존 사용자를 어떻게 해야 할지 고민됩니다. API 버전 관리를 도입하면 /v1/users는 그대로 두고, /v2/users에 새로운 기능을 추가할 수 있습니다.
기존 앱은 계속 작동하고, 새 앱은 새 버전을 사용합니다.
API 버전 관리란 API의 여러 버전을 동시에 운영하면서 점진적으로 업그레이드하는 전략입니다. 이 방식이 필요한 이유는 API가 한번 공개되면 많은 클라이언트가 의존하기 때문입니다.
모바일 앱은 사용자가 업데이트하지 않으면 옛날 버전 그대로입니다. 강제로 API를 바꾸면 그 앱들이 전부 망가집니다.
가장 일반적인 방법은 URL에 버전을 포함하는 것입니다. /v1/, /v2/처럼 경로 앞에 버전 번호를 붙입니다.
단순하고 명확해서 많은 회사들이 이 방식을 사용합니다. 핵심은 이전 버전을 일정 기간 유지하면서 새 버전으로의 이전을 유도하는 것입니다.
다음 코드를 살펴봅시다.
// URL 기반 버전 관리 (가장 일반적)
// /v1/users - 버전 1
// /v2/users - 버전 2 (새로운 응답 형식)
// Express에서 버전별 라우터 분리
const v1Router = express.Router();
const v2Router = express.Router();
// V1: 기존 응답 형식
v1Router.get('/users/:id', async (req, res) => {
const user = await User.findById(req.params.id);
res.json({
id: user.id,
name: user.name,
email: user.email
});
});
// V2: 개선된 응답 형식 (메타데이터 추가)
v2Router.get('/users/:id', async (req, res) => {
const user = await User.findById(req.params.id);
res.json({
data: {
id: user.id,
fullName: user.firstName + ' ' + user.lastName,
contact: { email: user.email, phone: user.phone }
},
meta: { version: 'v2', timestamp: new Date() }
});
});
// 버전별 라우터 등록
app.use('/v1', v1Router);
app.use('/v2', v2Router);
도입 스토리 서비스가 성장하면서 API 응답 형식을 개선해야 했다. 하지만 이미 10만 명이 사용하는 모바일 앱이 있었다.
개발팀은 /v2를 새로 만들어서 새 앱에 적용하고, /v1은 6개월간 유지하기로 했다. API 버전 관리란? 버전 관리는 API의 여러 버전을 동시에 운영하는 전략입니다.
마치 윈도우 10과 윈도우 11이 동시에 지원되는 것처럼, 사용자가 준비되면 새 버전으로 이동할 수 있게 합니다. 버전 관리 없이 변경할 때의 문제: - 일괄 중단: 모든 클라이언트가 동시에 영향받음 - 강제 업데이트: 앱 스토어 승인 기다리는 동안 서비스 중단 - 신뢰 상실: 갑작스러운 변경으로 개발자 불만 증가 버전 관리의 장점: - 점진적 이전: 클라이언트가 준비되면 이동 - 안정성: 기존 버전은 계속 동작 - 테스트 용이: 새 버전을 충분히 검증 후 공개 실제 동작 원리 1단계: /v1/users로 들어온 요청은 v1Router가 처리합니다.
2단계: /v2/users로 들어온 요청은 v2Router가 처리합니다. 3단계: 각 라우터는 해당 버전에 맞는 응답 형식을 반환합니다.
실무 활용 예시 결제 API를 업그레이드할 때, /v1/payments는 유지하면서 /v2/payments에 새 결제 수단을 추가합니다. 기존 결제는 그대로 동작합니다.
주의사항 너무 많은 버전을 유지하면 관리가 어렵습니다. 보통 최신 2-3개 버전만 지원하고, 오래된 버전은 폐기 예고 후 종료합니다.
실전 팁
💡 새 버전 출시 시 기존 버전의 폐기 일정을 미리 공지하세요
💡 주요 변경(breaking change)이 있을 때만 메이저 버전을 올리세요
6. URL_명명_규칙
/user_profile, /userProfile, /user-profile 중 어떤 게 맞을까요? 팀마다 다르게 쓰면 API가 뒤죽박죽이 됩니다.
URL 명명 규칙이 없으면 같은 프로젝트 안에서도 일관성이 깨집니다. 누군가는 camelCase로, 누군가는 snake_case로, 또 누군가는 kebab-case로 씁니다.
표준 명명 규칙을 정하면 팀 전체가 같은 스타일을 따르고, API 사용자도 패턴을 쉽게 예측할 수 있습니다.
URL 명명 규칙은 리소스 이름을 어떤 형식으로 쓸지 정하는 약속입니다. 가장 권장되는 방식은 kebab-case(하이픈 구분)입니다.
/user-profiles, /shopping-carts처럼 단어 사이에 하이픈을 넣습니다. 이유는 URL이 대소문자를 구분하지 않는 환경이 있고, 언더스코어는 밑줄과 혼동되기 쉽기 때문입니다.
다른 방식으로 camelCase(/userProfiles)나 snake_case(/user_profiles)도 있지만, 웹 URL 표준에서는 kebab-case를 선호합니다. 대형 기업들의 공개 API 대부분이 이 방식을 따릅니다.
중요한 것은 어떤 방식을 선택하든 프로젝트 전체에서 일관성을 유지하는 것입니다.
다음 코드를 살펴봅시다.
// 명명 규칙 비교
// snake_case: /user_profiles (Python 스타일)
// camelCase: /userProfiles (JavaScript 스타일)
// kebab-case: /user-profiles (URL 권장 스타일)
// kebab-case URL 예시 (권장)
// /user-profiles
// /shopping-carts
// /order-items
// /product-categories
// 실제 라우터 구현
const router = express.Router();
// kebab-case URL 사용
router.get('/user-profiles', getAllUserProfiles);
router.get('/user-profiles/:id', getUserProfile);
router.post('/user-profiles', createUserProfile);
router.get('/shopping-carts', getShoppingCarts);
router.get('/shopping-carts/:id/cart-items', getCartItems);
router.get('/product-categories', getProductCategories);
router.get('/product-categories/:categoryId/sub-categories', getSubCategories);
// 주의: URL은 kebab-case, JSON 응답은 camelCase가 일반적
router.get('/user-profiles/:id', async (req, res) => {
const profile = await UserProfile.findById(req.params.id);
res.json({
userId: profile.user_id, // JSON은 camelCase
firstName: profile.first_name,
createdAt: profile.created_at
});
});
도입 스토리 새 팀원이 합류해서 API 엔드포인트를 추가했는데, 기존의 /user-profiles 옆에 /shoppingCart가 생겼다. 코드 리뷰에서 "우리는 kebab-case를 쓰기로 했어요"라는 피드백을 받았다.
URL 명명 규칙이란? 명명 규칙은 이름을 짓는 방식을 통일하는 약속입니다. 마치 회사에서 파일명을 "날짜_제목_버전" 형식으로 통일하는 것처럼, URL도 일관된 형식을 따릅니다.
명명 규칙이 없을 때의 문제: - 혼란: /getUserData와 /get-user-data가 다른 API인지 같은 건지 헷갈림 - 오타: 대소문자 실수로 404 에러 발생 - 문서화 어려움: 일관성 없는 패턴은 설명하기 어려움 kebab-case의 장점: - 가독성: 단어 구분이 명확함 - 안전성: URL은 대소문자 무시하는 환경이 있어서 소문자가 안전 - 표준: 대부분의 공개 API가 이 방식 사용 실제 동작 원리 1단계: URL 설계 시 모든 리소스 이름을 kebab-case로 통일합니다. 2단계: 복합어는 하이픈으로 연결합니다 (product-categories).
3단계: 팀 내 코드 리뷰에서 명명 규칙 준수를 확인합니다. 실무 활용 예시 GitHub API(/user-repos), Stripe API(/payment-methods), Twitter API(/user-timeline) 등 유명 API들이 kebab-case를 사용합니다.
주의사항 URL은 kebab-case를 쓰더라도, JSON 응답 본문은 camelCase를 쓰는 것이 JavaScript와 잘 맞습니다. 두 가지를 혼동하지 마세요.
실전 팁
💡 URL은 kebab-case, JSON은 camelCase로 구분해서 사용하세요
💡 팀 위키에 명명 규칙을 문서화해두면 새 팀원도 바로 따라할 수 있습니다
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
WebSocket과 Server-Sent Events 실시간 통신 완벽 가이드
웹 애플리케이션에서 실시간 데이터 통신을 구현하는 핵심 기술인 WebSocket과 Server-Sent Events를 다룹니다. 채팅, 알림, 실시간 업데이트 등 현대 웹 서비스의 필수 기능을 구현하는 방법을 배워봅니다.
API 테스트 전략과 자동화 완벽 가이드
API 개발에서 필수적인 테스트 전략을 단계별로 알아봅니다. 단위 테스트부터 부하 테스트까지, 실무에서 바로 적용할 수 있는 자동화 기법을 익혀보세요.
효과적인 API 문서 작성법 완벽 가이드
API 문서는 개발자와 개발자 사이의 가장 중요한 소통 수단입니다. 이 가이드에서는 좋은 API 문서가 갖춰야 할 조건부터 Getting Started, 엔드포인트 설명, 에러 코드 문서화, 인증 가이드, 변경 이력 관리까지 체계적으로 배워봅니다.
API 캐싱과 성능 최적화 완벽 가이드
웹 서비스의 응답 속도를 획기적으로 개선하는 캐싱 전략과 성능 최적화 기법을 다룹니다. HTTP 캐싱부터 Redis, 데이터베이스 최적화, CDN까지 실무에서 바로 적용할 수 있는 핵심 기술을 초급자 눈높이에서 설명합니다.
OAuth 2.0과 소셜 로그인 완벽 가이드
OAuth 2.0의 핵심 개념부터 구글, 카카오 소셜 로그인 구현까지 초급 개발자를 위해 쉽게 설명합니다. 인증과 인가의 차이점, 다양한 Flow의 특징, 그리고 보안 고려사항까지 실무에 바로 적용할 수 있는 내용을 다룹니다.