-
📝 학습 목표
-
🤔 개발 설계 단계!
-
✒️ 0. 들어가기 전
-
✒️ 1. API 란?
-
✒️ 2. REST API
-
✒️ 3. API Endpoint
-
✒️ 4. HTTP 메소드
-
✒️ 5. RESTful API Endpoint의 설계
-
💡 설계 규칙
-
💡 회원 가입, 로그인, 탈퇴
-
💡 리소스 간 연관 관계가 있는 경우
-
✒️ 6. 세부적인 API 설계
-
💡 회원가입에 대한 고민
-
💡 Path Variable
-
💡 Query String
-
💡 Request Body
-
💡 Request Header
-
✒️ 7. API 설계 예시
-
💡 API EndPoint
-
💡 Request Body
-
💡 Request Header
-
💡 Query String
-
✒️ 8. 프로젝트 세팅하기
-
💡 Spring Boot - 추가자료
📝 학습 목표
- RESTful한 API 설계를 익힌다.
- Node.js, Spring boot의 프로젝트 세팅을 한다.
🤔 개발 설계 단계!
개발을 공부하고, 팀 프로젝트를 하다보면
가장 크게 느끼는 점이 "설계"에 많은 시간을 투자해야 한다는 점을 뼈져리게 느낀다는 것이다.
컴공에서 배우는 이론적인 이야기에 "설계"에 많은 시간을 쏟은 것도
당시에는 '왜 이런걸 배울까' 스트레스도 받았지만,
정말 정작 중요한 것은 "설계" 였다...
설계만 잘 해놓아도, 개발 과정의 혼란을 줄일 수 있다!
대충만 순서를 말해보자면,
요구사항 분석 후 명세서를 작성하고,
ERD를 그려 엔티티간의 관계를 정의한다.
바로 저번주에 ERD를 그려보았다!
그리고 이후에 하는 것이 바로 API 설계!
RESTful API 등의 스타일을 정하고, URL 구조, HTTP 메서드, 요청/응답 포맷 등을 정의한다!
그리고 나서야 전체 시스템의 아키텍쳐를 설계하는 것이다.
물론, 이 API 설계 또한 큰 틀에서 설계하는 것이며, 처음부터 완벽하게 설계할 수는 없다.
✒️ 0. 들어가기 전
들어가기 앞서, API 설계에 필요한 것은 무엇일까?
크게 보자면 2가지 이다.
1. API End Point 설계
2. 요청 / 응답 데이터의 설계
그리고, 위의 정보를 문서화 하여, 프론트 개발자가 API 를 사용하기 쉽도록 돕는 문서를 API 명세서 라고 한다!
우리는 API 설계에 대해 배워보고, 프로젝트에 들어가기 앞서 세팅을 해 볼 것이다.
✒️ 1. API 란?
일단 가장 먼저 "어떠한 개념"에 대해 공부할 때 좋은 것은 "정의"를 찾아보는 것이다.
Application Programming Interface (API)
API라는 얘기는 주변에서 정말 많이 들어봤을 것이다.
그러나, 개발관련 단어를 처음보면 느끼는점.....
이거 여기서도 저기서도 다 다르게 쓰이는 거 같아......
마치..코에 걸면 코걸이, 귀에 걸면 귀걸이 처럼
'아~ 대충 이런 느낌이구나' 정도로만 알고 있을 것이다...
이렇듯 많은 분들이 API를 클라이언트와 서버 간 통신에 필요한 것 정도로만 이해를 하고 있다.
🌟 Application을 Programming 할 때 사용되는 인터페이스
인터페이스는 일상생활에서 많이 접할 수 있다.
User Interface의 약자인 UI는 간단히 말해서,
어려운 것은 감추고 보다 쉽게 상호작용 할 수 있도록 해주는 것들을 의미한다.
여담으로 조금 더 포괄적으로 말해 보자면,
프로그래밍 뿐만 아니라, "소프트웨어 컴포넌트 간의 상호작용을 위한 인터페이스" 를 의미하기도 한다.
(참... 개발 공부하고, 용어공부하면 느끼는 것이 '이 사람들은 언어에서 까지도 "다형성"을 적용시켰구나.' 라는 것을 느낀다..
같은 단어를 비슷한 맥락에서 많이 돌려 쓰는 것 같다...)그래서, 우리가 지금 말하는 웹 API 말고도, 라이브러리 API, 프레임워크 API, 서드파트 API 등도 있고,
느낌만 정확히 파악하면 다 똑같은 API의 의미라는 것을 알 수 있다.
다시 본론으로 돌아와서
🌟 API는 애플리케이션을 프로그래밍 할 때, 보다 쉽게 할 수 있도록 해주는 도구들을 의미한다!
예시로 Js에서 console.log 나 python에서 print
모두 콘솔에 출력을 해주는 함수인데,
어떻게 콘솔에 출력을 해줄까..?
몰라~ 내부 로직은 시스템콜이 어떻게 돌아가는지 몰라도 된다.
이 또한 API라고 부른다!
API 라는 단어에 추상화, 캡슐화의 개념이 들어간 것도 느끼며 넘어가자.
Query 또한 DB 설계와 마찬가지로 정해진 답은 없다!
✒️ 2. REST API
REST는 Representational State Transfer의 약자이다.
HTTP를 기반으로 하는 웹 서비스 아키텍처를 의미하며,
HTTP 메소드와 자원을 이용해 서로 간의 통신을 주고받는 방법이다.
✒️ 3. API Endpoint
REST API에서 API Endpoint는 해당 API를 호출하기 위한 HTTP 메소드, 그리고 URL을 포함한다.
✒️ 4. HTTP 메소드
HTTP 메소드는 REST 방식으로 통신할 때 필요한 작업의 행위를 표시하는 방법이다.
지금 소개하는 5가지 말고도, 더욱 많지만
가장 자주 쓰이는 5가지만 소개해본다.
1. GET : 조회
2. POST : 생성
3. PUT : 갱신 (전체)
4. PATCH : 갱신 (일부)
5. DELETE : 삭제
물론, POST는 새로운 자원의 생성의 의미도 있지만,
특정 정보를 서버로 넘기고, 그에 대한 처리를 요청하는 것도
전부 POST로 처리하기도 한다.
✒️ 5. RESTful API Endpoint의 설계
💡 설계 규칙
RESTful한 API의 Endpoint는 아래의 규칙에 따라 설계가 가능하다.
1. URI에 동사가 포함이 되어선 안된다.
2. URI에서 단어의 구분이 필요한 경우 -(하이픈)을 이용한다.
3. 자원은 기본적으로 복수형으로 표현한다.
4. 단 하나의 자원을 명시적으로 표현을 하기 위해서는 /users/id와 같이 식별 값을 추가로 사용한다.
5. 자원 간 연관 관계가 있을 경우 이를 URI에 표현한다.
5번은 추가적인 설명이 필요하나, 나머지는 쉽게 감이 올 것이다.
이제 예시를 보면서 REST API 설계를 어떻게 하는지 살펴보자!
💡 회원 가입, 로그인, 탈퇴
- 로그인
사실 규칙대로 하기에는 조금의 "융통성"이 필요한 부분이다...
로그인의 주체가 되는 대상은 사용자 이므로,
users 라는 자원이 들어가는 것은 쉽게 눈치챘을 것이다.
로그인에 필요한 정보를 서버로 넘겨 로그인에 대한 처리를 요청하는 것이니 POST를 쓰는 것 까지도 이해가 된다.
그럼 그냥 POST /users 하면 끝일까?
그렇다면, 회원가입이고 뭐고 모든 사용자 관련 처리 요청은 POST /users 로 통일될 것이다...
이럴 땐 융통성을 발휘하여
POST /users/login
이런 식으로 동사를 활용하여 명시하는 것이 오히려 올바른 설계 방식이다.
추가적으로, 스프링 시큐리티를 사용해서 인증을 구현한다고 가정하자.
그렇다면 별도의 경로 설정이 없을 경우,
default 로그인 경로가 "/login"으로 되어있기 떄문에,
로그인은 가급적이면 /login 으로 맞추는 것이 좋다.
(물론 설정을 통해 경로를 바꿀 수는 있다.)
- 회원가입
로그인을 명시적으로 처리해주었기 때문에,
회원가입을 POST /users 로 설계해도 된다
다만, 이것 역시 요구사항을 고려해봐야한다.
만약에, 회원 가입 외에 사용자를 추가해야하는 다른 기능이 있다면??
이와 구분해야 한다!
그러므로 이 또한,
POST /users/signup 혹은
POST /users/register 등으로 명시적인 설계가 필요하다.
(위와 같은 경우가 아니라면, 회원가입은 POST /users 로 두어도 큰 문제는 없다!)
🤔 잠시만! 회원 가입은 유저 한 명을 새로 만드는 것인데, POST /users/{userId} 아닌가?
해당 형태로 설계한다면, 해당 유저를 식별할 userId값이 있어야 한다.
그러나 회원 가입 전에는 유저 엔티티가 생성되기 이전이므로,
유저 식별자가 API 호출 지점에 없기 때문에
해당 방식의 설계는 물리적으로 불가능하다....
- 탈퇴
단순히 생각하면 HTTP Method 의 구분만으로
DELETE /users 라고 생각하기 좋다.
다만, 곧바로 데이터베이스에서 계정을 삭제하는 HARD DELETE 방식이 아닌,
추후 계정 복구를 고라하여 계정을 비활성화시키는 SOFT DELETE 방식이라면,
다른 방식을 고려해 보아야 한다.
즉, 사용자 테이블의 status를 actvie 에서 inactvie로 변경하는 것이기에
일부 수정인 PATCH를 사용하는 것이 더 올바른 설계이다.
PATCH /users
사실 이것도 요구사항에 따라 변할 수 있다.
User에 관련된 모든 수정이 또 이 하나의 url에 겹치게 된다.
이럴 때면, userid로 구분해주어도 된다.
사용자 테이블의 일부 정보 수정을
PATCH /users/{userId}
회원 탈퇴는
PATCH /users 로 표현하기도 한다.
다만, 프론트와의 명확한 소통이 목적이기에 이렇게 애매하기 설계하기 보다,
PATCH /users/delete
와 같이 명시적으로 설계하는 것이 더 좋다.
결론은 또, API 설계에는 절대적인 정답은 없다는 것
되도록 5개의 규칙을 지키려고 하되, 불가피한 경우 융통성을 발휘하자!
역시 또 나온 개발자의 역량 ... 소통 ...
💡 리소스 간 연관 관계가 있는 경우
예를 들어, 교과목이 한 명의 user(교사)가 여러 개의 교과목을 강의할 수 있다고 하자.
교사와 교과목이 1:N 관계라고 볼 수 있다.
"교과목의 목록을 조회하는 API를 설계한다고 가정해보자"
( 편의를 위해 사용자는 오로지 교사만 있다고 가정, user = 교사 )
/users/subjects
이런식으로 설계할 수 있다!
교사가 여러개의 과목을 강의하기에는 계층 관계는 교사 -> 다음 교과목으로 잡고
uri 상에 교사가 더 계층 관계상 우선이 된다는 것을 표현할 수 있다!
그렇다면 특정 user(교사)의 subject만을 설계한다면?
/users/{userId}/subjects
로 표현이 가능하다.
- 만약, 교과목 하나 단 건 조회 API를 설계한다면?
다음 고민을 해볼 차례이다.
1. 특정 교사의 특정 교과목이 의미 전달이 올바를까?
2. 특정 교과목의 특정 교사가 의미 전달이 올바를까?
이에 따라 서순을 정해주면 된다!
특정 교사의 특정 교과목이라면
/users/{userId}/subjects/{subjectId}
혹은 교사와 상관없이 그저 "수학"과 같은 교과목 하나를 뽑아 내고 싶다면?
/users/subjects/{subjectId}
- N:M 관계는?
API 설계할 때 가장 골이 아픈 경우이다..
EX) 게시글과 해시태그의 관계
여러 개의 게시글에 여러 개의 해시태그가 붙을 수 있다.
🤔 /articles/hash-tags
🤔 /hash-tags/articles
결국 이것도, "비즈니스 로직상 더 중요한 대상을 계층 관계상 앞에 두는 것"이 좋다.
직관적인 해석에 용이하기 때문이다. (결국 또 소통...)
해시태그는 게시글에 부속적으로 있는 것이고,
게시글이 서비스에서 더 중점적인 역할을 한다는 것을 느낄 수 있다.
보통 해석할 때 "어떤 게시물의 어떤 해시태그" 라고 해석하기 때문이다.
/articles/hash-tags
결국, 설계 단계에서 중요한 것은 타 부서와의 소통이기 때문에
모호하다고 판단되면 혼자 결정하지말고, 타 부서와의 많은 커뮤니케이션이 중요하다!
✒️ 6. 세부적인 API 설계
이제 세부적인 API 설계에 대해 고민해보자.
아래의 키워드를 설계단계에서 고려해야 한다.
1. Path Variable
2. Query String
3. Request Body
4. Request Header
사실, 위 4개 중 API Endpoitn (URI)에 직접 적으로 포함되는 것은 첫 번째 Path Variable 뿐이다.
포스팅 초반에 말했듯이 API 설계란,
RESTful API 등의 스타일을 정하고, URL 구조, HTTP 메서드, 요청/응답 포맷 등을 정의한다! 고 했다.
API EndPoint로 알 수있는 정보는 Http Method(역할) 와 말그대로 resource의 최종 도착지점 뿐이다.
💡 회원가입에 대한 고민
그렇다.... POST /users 로 끝인가?
회원 정보를 저장하는 거잖아!
무슨 정보를 저장하는데?
그리고 무슨 응답을 줄건데..?
여러 가지 정보가 누락되어 있다.
이런 경우 위 4가지를 사용하게 된다.
천천히 알아보자.
💡 Path Variable
게시글 하나 상세 조회 API 를 설계한다고 해보자.
1 건 조회??
이제 쉽게 GET 메소드를 떠올리게 될 것이다!
그런데, 어떻게 특정 게시글임을 서버에게 전달이 가능할까?
다시 말해, 서버에게 어떻게 원하는 게시글을 식별할 수 있는 데이터를 넘길 수 있을까?
이런 경우에 path variable을 사용한다.
단 하나, 특정 대상을 지목할 때
/users/articles/{userId} 처럼 id에 게시글의 식별 값을 넣어서 전달한다.
예시를 보자면,
GET https://tistory.com/users/articles/4
서버는 해당 {userId}로 4라는 숫자를 받으면,
서버는 데이터베이스 상에서 4번째 게시글의 기본키라는 것을 캐치할 수 있다.
실제 API 명세서에서는 아래처럼 표현한다!
🔑 GET /users/articles/{articleId}
{ }(중괄호)로 감싸는 부분은 path variable을 의미한다!
그냥 id 보다는 articleId처럼 더 명시적으로 표현해주는 것이 더 좋다.
규칙중 단어 구분을 -를 사용해서 한다 규칙이 있었다.
규칙상으로는
🔑 GET /users/articles/{article-id}
이 맞지만,
관용적으로
대부분 {articleId}의 형식으로 표현하는 것 같다.
🔑 GET /users/articles/{articleId}
💡 Query String
그렇다면 쿼리 스트링은 언제 사용되는가?
게시글 중에서 이름에 umc가 포함된 게시글들을 조회하려고 할 때!
이럴 경우, 하나가 아니라 여러 개가 될 수도 있다!
즉, id로 특정하여 하나만을 조회하지 못할 수 있다는 이야기다.
path variable 사용하기 어렵다...
이럴 때 Query String을 활용할 수 있다!
보통 쿼리 스트링은 "검색 조회" 때 사용 된다.
따라서 GET 요청에서만 사용하는 것이 규칙!
GET /users/articles?name=umc
또한, 여러 개의 정보를 전달하고 싶다면??
&를 활용하면 된다!
GET /users/articles?name=umc&owner=ddol
이런 형태는 많이 보았을 것이다!

예시로 해당 uri 도 어떻게 구성되어 있나 보자.
Host : ~~naver.com 부분 뒷 부분만 보자면,
경로 (Path): /search.naver 서버 내에서 요청을 처리할 리소스의 경로
이 경우에는 네이버 검색 엔진의 검색 기능을 받는 Endpoint이다.쿼리 파라미터 (Query Parameters):
- where=nexearch: 검색 영역을 지정한다.
- sm=top_sug.pre, fbm=0, acr=3, qdt=0 등의 파라미터 들이 &로 엮여 있다.
(의미는 몰라도 된당~ 형식만 보는중)
- acq=%EC%95%88%EB%85%95: 자동 완성 쿼리로, 한글 "안녕"이 URL 인코딩되어 있다.해당 URI는 네이버 검색 엔진에서 "안녕"이라는 검색어로 검색을 수행하는 요청을 나타낸다.
이 URI를 통해 클라이언트는 네이버 검색 서버에 "안녕"이라는 검색어에 대한 검색 결과를 요청하고,
서버는 해당 검색어에 대한 검색 결과를 반환할 것이다.


🚨주의 : 쿼리 스트링은 API 엔드포인트에 포함되지는 않기 때문에,
엔드포인트 자체에는 GET /users/articles 로 설계해야 하며
쿼리 스트링의 양식은 세부 사항이나, 예시 쪽에 써주는 것이 좋다.
💡 Request Body
POST는 실제 DB의 자원을 생성하는 메서드이다.
조회가 아닌 "생성"에 관한 메서드이기 때문에,
DB의 데이터를 변경할 수 있다는 점에서 매우 보안적으로 신경써야하는 부분이다.
즉, url에 resource들을 모두 노출시키는 것은 매우 좋지 않은 설계이다.
따라서, url에 노출시키지 않고, request body에 해당 데이터를 담을 수 있다.
형태는 Json 형식 혹은 Form-data 형식이 있다.
RESTful API의 경우, JSON 형식을 주로 사용한다!
JSON은 데이터 교환에 있어서 경량화되고 읽기 쉬운 형식으로 사용되고 있다.
다만, 파일 업로드와 같은 바이너리 데이터 전송이 필요한 경우에는 Form-data 형식이 사용된다.
사실 웹 브라우저에서 기본적으로 지원하는 형식은 form-data라는 것...
어쨌든, 회원가입의 정보를 request body에 담아서 json 형식으로 서버에 전송한다면, 다음 형식으로 보낼 수 있다.
{
“name” : “김진호”,
“phoneNum” : “010-1111-2222”,
"nickName" : "ricky",
}
💡 Request Header
마지막 Header이다.

'뭐야? "목적지(EndPoint)"에 정확한 내용물(Json)을 박스(RequestBody)에 담아서 보내면 끝나거 아냐?'
뭘 또 해야하나....
하지만 하나 빠뜨린게 있는듯 한데...?
바로 "송장"!

그 박스를 목적지까지 무사히 전달하려면 몇 가지 추가 정보가 필요할 겁니다.
예를 들면...
내용물이 무엇인지 (Content-Type)
박스의 크기는 어느 정도인지 (Content-Length)
박스를 받는 사람은 누구인지 (Host)
박스를 보내는 사람은 누구인지 (User-Agent)
등등...
이러한 추가 정보들이 바로 Request Header에 해당한다.
Request Header는 마치 박스에 붙이는 송장이나 라벨 같은 역할을 한다고 생각하면 편할 것 같다.
✒️ 7. API 설계 예시
예를 들어 닉네임 변경(사용자 정보 변경) API에 대한 설계를 한다고 가정해보자.
아래와 같은 정보를 명시할 수 있다.
💡 API EndPoint
PATCH /users/{userId}
💡 Request Body
{
"nickname" : "ddol"
}
💡 Request Header
Authorization : accessToken (String)
accessToken은 로그인 된 사용자가 나 로그인 된 상태야! 하고 인증해주는 것으로
(회사 문 통과할 때 쓰는 키 정도로 생각)
보통 Authorization이라는 키에 대한 값으로 헤더에 담아서 서버로 보내주게 된다.
(Filter에서 인증 통과하면 "너 인정!" 외치고 들여보내준다.)
💡 Query String
현재는 필요 없음
✒️ 8. 프로젝트 세팅하기
💡 Spring Boot - 추가자료
프로젝트 세팅 하는 글은 내 포스팅에도 많고, 구글링해도 너무 많이 나와서 생략한다..
1. 통신
HTTP/HTTPS 통신 & RESTful API
1. HTTP/HTTPS 통신 웹 브라우저와 웹 서버 간의 통신은 주로 HTTP(또는 HTTPS) 프로토콜을 사용한다. 1) HTTP/HTTP HTTP(Hyper Text Transfer Protocol) 란? 클라이언트(웹 브라우저)가 서버에 요청을 보내고, 서버가
jinhos-devlog.tistory.com
2. JSON
JSON이란?
1. JSON이란? JSON(JavaScript Object Notation)은 데이터 교환을 위한 경량의 데이터 교환 형식이다. (XML과 같은 다른 형식도 있다.) JSON은 인간이 읽고 쓰기 쉽고, 기계적으로 파싱하고 생성하기도 쉽다는
jinhos-devlog.tistory.com
3. JAVA를 공부하기 전에 알두면 좋을 것들
0. JAVA를 공부하기 전에 알두면 좋을 것들
다음은 글은 infrean의 "자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]" 강의의 학습 목적으로 작성된 것입니다. 강의의 디테일한 내용
jinhos-devlog.tistory.com
4. 프로젝트 세팅 / API 만들기
1. API 만들기
다음은 글은 infrean의 "자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]" 강의의 학습 목적으로 작성된 것입니다. 강의의 디테일한 내용
jinhos-devlog.tistory.com
5. Spring Initializr에서 Gradle-groovy와 -Kotlin의 차이
Spring Initializr에서 Gradle-groovy와 -Kotlin의 차이
Gradle은 빌드 자동화 도구이며, Groovy와 Kotlin 두 가지 언어를 사용하여 빌드 스크립트를 작성할 수 있다. 이전에는 다음과 같이 Gradle과 Maven으로만 빌드 툴이 나누어져 있었다면, 최근에는 Groovy와
jinhos-devlog.tistory.com
📝 학습 목표
- RESTful한 API 설계를 익힌다.
- Node.js, Spring boot의 프로젝트 세팅을 한다.
🤔 개발 설계 단계!
개발을 공부하고, 팀 프로젝트를 하다보면
가장 크게 느끼는 점이 "설계"에 많은 시간을 투자해야 한다는 점을 뼈져리게 느낀다는 것이다.
컴공에서 배우는 이론적인 이야기에 "설계"에 많은 시간을 쏟은 것도
당시에는 '왜 이런걸 배울까' 스트레스도 받았지만,
정말 정작 중요한 것은 "설계" 였다...
설계만 잘 해놓아도, 개발 과정의 혼란을 줄일 수 있다!
대충만 순서를 말해보자면,
요구사항 분석 후 명세서를 작성하고,
ERD를 그려 엔티티간의 관계를 정의한다.
바로 저번주에 ERD를 그려보았다!
그리고 이후에 하는 것이 바로 API 설계!
RESTful API 등의 스타일을 정하고, URL 구조, HTTP 메서드, 요청/응답 포맷 등을 정의한다!
그리고 나서야 전체 시스템의 아키텍쳐를 설계하는 것이다.
물론, 이 API 설계 또한 큰 틀에서 설계하는 것이며, 처음부터 완벽하게 설계할 수는 없다.
✒️ 0. 들어가기 전
들어가기 앞서, API 설계에 필요한 것은 무엇일까?
크게 보자면 2가지 이다.
1. API End Point 설계
2. 요청 / 응답 데이터의 설계
그리고, 위의 정보를 문서화 하여, 프론트 개발자가 API 를 사용하기 쉽도록 돕는 문서를 API 명세서 라고 한다!
우리는 API 설계에 대해 배워보고, 프로젝트에 들어가기 앞서 세팅을 해 볼 것이다.
✒️ 1. API 란?
일단 가장 먼저 "어떠한 개념"에 대해 공부할 때 좋은 것은 "정의"를 찾아보는 것이다.
Application Programming Interface (API)
API라는 얘기는 주변에서 정말 많이 들어봤을 것이다.
그러나, 개발관련 단어를 처음보면 느끼는점.....
이거 여기서도 저기서도 다 다르게 쓰이는 거 같아......
마치..코에 걸면 코걸이, 귀에 걸면 귀걸이 처럼
'아~ 대충 이런 느낌이구나' 정도로만 알고 있을 것이다...
이렇듯 많은 분들이 API를 클라이언트와 서버 간 통신에 필요한 것 정도로만 이해를 하고 있다.
🌟 Application을 Programming 할 때 사용되는 인터페이스
인터페이스는 일상생활에서 많이 접할 수 있다.
User Interface의 약자인 UI는 간단히 말해서,
어려운 것은 감추고 보다 쉽게 상호작용 할 수 있도록 해주는 것들을 의미한다.
여담으로 조금 더 포괄적으로 말해 보자면,
프로그래밍 뿐만 아니라, "소프트웨어 컴포넌트 간의 상호작용을 위한 인터페이스" 를 의미하기도 한다.
(참... 개발 공부하고, 용어공부하면 느끼는 것이 '이 사람들은 언어에서 까지도 "다형성"을 적용시켰구나.' 라는 것을 느낀다..
같은 단어를 비슷한 맥락에서 많이 돌려 쓰는 것 같다...)그래서, 우리가 지금 말하는 웹 API 말고도, 라이브러리 API, 프레임워크 API, 서드파트 API 등도 있고,
느낌만 정확히 파악하면 다 똑같은 API의 의미라는 것을 알 수 있다.
다시 본론으로 돌아와서
🌟 API는 애플리케이션을 프로그래밍 할 때, 보다 쉽게 할 수 있도록 해주는 도구들을 의미한다!
예시로 Js에서 console.log 나 python에서 print
모두 콘솔에 출력을 해주는 함수인데,
어떻게 콘솔에 출력을 해줄까..?
몰라~ 내부 로직은 시스템콜이 어떻게 돌아가는지 몰라도 된다.
이 또한 API라고 부른다!
API 라는 단어에 추상화, 캡슐화의 개념이 들어간 것도 느끼며 넘어가자.
Query 또한 DB 설계와 마찬가지로 정해진 답은 없다!
✒️ 2. REST API
REST는 Representational State Transfer의 약자이다.
HTTP를 기반으로 하는 웹 서비스 아키텍처를 의미하며,
HTTP 메소드와 자원을 이용해 서로 간의 통신을 주고받는 방법이다.
✒️ 3. API Endpoint
REST API에서 API Endpoint는 해당 API를 호출하기 위한 HTTP 메소드, 그리고 URL을 포함한다.
✒️ 4. HTTP 메소드
HTTP 메소드는 REST 방식으로 통신할 때 필요한 작업의 행위를 표시하는 방법이다.
지금 소개하는 5가지 말고도, 더욱 많지만
가장 자주 쓰이는 5가지만 소개해본다.
1. GET : 조회
2. POST : 생성
3. PUT : 갱신 (전체)
4. PATCH : 갱신 (일부)
5. DELETE : 삭제
물론, POST는 새로운 자원의 생성의 의미도 있지만,
특정 정보를 서버로 넘기고, 그에 대한 처리를 요청하는 것도
전부 POST로 처리하기도 한다.
✒️ 5. RESTful API Endpoint의 설계
💡 설계 규칙
RESTful한 API의 Endpoint는 아래의 규칙에 따라 설계가 가능하다.
1. URI에 동사가 포함이 되어선 안된다.
2. URI에서 단어의 구분이 필요한 경우 -(하이픈)을 이용한다.
3. 자원은 기본적으로 복수형으로 표현한다.
4. 단 하나의 자원을 명시적으로 표현을 하기 위해서는 /users/id와 같이 식별 값을 추가로 사용한다.
5. 자원 간 연관 관계가 있을 경우 이를 URI에 표현한다.
5번은 추가적인 설명이 필요하나, 나머지는 쉽게 감이 올 것이다.
이제 예시를 보면서 REST API 설계를 어떻게 하는지 살펴보자!
💡 회원 가입, 로그인, 탈퇴
- 로그인
사실 규칙대로 하기에는 조금의 "융통성"이 필요한 부분이다...
로그인의 주체가 되는 대상은 사용자 이므로,
users 라는 자원이 들어가는 것은 쉽게 눈치챘을 것이다.
로그인에 필요한 정보를 서버로 넘겨 로그인에 대한 처리를 요청하는 것이니 POST를 쓰는 것 까지도 이해가 된다.
그럼 그냥 POST /users 하면 끝일까?
그렇다면, 회원가입이고 뭐고 모든 사용자 관련 처리 요청은 POST /users 로 통일될 것이다...
이럴 땐 융통성을 발휘하여
POST /users/login
이런 식으로 동사를 활용하여 명시하는 것이 오히려 올바른 설계 방식이다.
추가적으로, 스프링 시큐리티를 사용해서 인증을 구현한다고 가정하자.
그렇다면 별도의 경로 설정이 없을 경우,
default 로그인 경로가 "/login"으로 되어있기 떄문에,
로그인은 가급적이면 /login 으로 맞추는 것이 좋다.
(물론 설정을 통해 경로를 바꿀 수는 있다.)
- 회원가입
로그인을 명시적으로 처리해주었기 때문에,
회원가입을 POST /users 로 설계해도 된다
다만, 이것 역시 요구사항을 고려해봐야한다.
만약에, 회원 가입 외에 사용자를 추가해야하는 다른 기능이 있다면??
이와 구분해야 한다!
그러므로 이 또한,
POST /users/signup 혹은
POST /users/register 등으로 명시적인 설계가 필요하다.
(위와 같은 경우가 아니라면, 회원가입은 POST /users 로 두어도 큰 문제는 없다!)
🤔 잠시만! 회원 가입은 유저 한 명을 새로 만드는 것인데, POST /users/{userId} 아닌가?
해당 형태로 설계한다면, 해당 유저를 식별할 userId값이 있어야 한다.
그러나 회원 가입 전에는 유저 엔티티가 생성되기 이전이므로,
유저 식별자가 API 호출 지점에 없기 때문에
해당 방식의 설계는 물리적으로 불가능하다....
- 탈퇴
단순히 생각하면 HTTP Method 의 구분만으로
DELETE /users 라고 생각하기 좋다.
다만, 곧바로 데이터베이스에서 계정을 삭제하는 HARD DELETE 방식이 아닌,
추후 계정 복구를 고라하여 계정을 비활성화시키는 SOFT DELETE 방식이라면,
다른 방식을 고려해 보아야 한다.
즉, 사용자 테이블의 status를 actvie 에서 inactvie로 변경하는 것이기에
일부 수정인 PATCH를 사용하는 것이 더 올바른 설계이다.
PATCH /users
사실 이것도 요구사항에 따라 변할 수 있다.
User에 관련된 모든 수정이 또 이 하나의 url에 겹치게 된다.
이럴 때면, userid로 구분해주어도 된다.
사용자 테이블의 일부 정보 수정을
PATCH /users/{userId}
회원 탈퇴는
PATCH /users 로 표현하기도 한다.
다만, 프론트와의 명확한 소통이 목적이기에 이렇게 애매하기 설계하기 보다,
PATCH /users/delete
와 같이 명시적으로 설계하는 것이 더 좋다.
결론은 또, API 설계에는 절대적인 정답은 없다는 것
되도록 5개의 규칙을 지키려고 하되, 불가피한 경우 융통성을 발휘하자!
역시 또 나온 개발자의 역량 ... 소통 ...
💡 리소스 간 연관 관계가 있는 경우
예를 들어, 교과목이 한 명의 user(교사)가 여러 개의 교과목을 강의할 수 있다고 하자.
교사와 교과목이 1:N 관계라고 볼 수 있다.
"교과목의 목록을 조회하는 API를 설계한다고 가정해보자"
( 편의를 위해 사용자는 오로지 교사만 있다고 가정, user = 교사 )
/users/subjects
이런식으로 설계할 수 있다!
교사가 여러개의 과목을 강의하기에는 계층 관계는 교사 -> 다음 교과목으로 잡고
uri 상에 교사가 더 계층 관계상 우선이 된다는 것을 표현할 수 있다!
그렇다면 특정 user(교사)의 subject만을 설계한다면?
/users/{userId}/subjects
로 표현이 가능하다.
- 만약, 교과목 하나 단 건 조회 API를 설계한다면?
다음 고민을 해볼 차례이다.
1. 특정 교사의 특정 교과목이 의미 전달이 올바를까?
2. 특정 교과목의 특정 교사가 의미 전달이 올바를까?
이에 따라 서순을 정해주면 된다!
특정 교사의 특정 교과목이라면
/users/{userId}/subjects/{subjectId}
혹은 교사와 상관없이 그저 "수학"과 같은 교과목 하나를 뽑아 내고 싶다면?
/users/subjects/{subjectId}
- N:M 관계는?
API 설계할 때 가장 골이 아픈 경우이다..
EX) 게시글과 해시태그의 관계
여러 개의 게시글에 여러 개의 해시태그가 붙을 수 있다.
🤔 /articles/hash-tags
🤔 /hash-tags/articles
결국 이것도, "비즈니스 로직상 더 중요한 대상을 계층 관계상 앞에 두는 것"이 좋다.
직관적인 해석에 용이하기 때문이다. (결국 또 소통...)
해시태그는 게시글에 부속적으로 있는 것이고,
게시글이 서비스에서 더 중점적인 역할을 한다는 것을 느낄 수 있다.
보통 해석할 때 "어떤 게시물의 어떤 해시태그" 라고 해석하기 때문이다.
/articles/hash-tags
결국, 설계 단계에서 중요한 것은 타 부서와의 소통이기 때문에
모호하다고 판단되면 혼자 결정하지말고, 타 부서와의 많은 커뮤니케이션이 중요하다!
✒️ 6. 세부적인 API 설계
이제 세부적인 API 설계에 대해 고민해보자.
아래의 키워드를 설계단계에서 고려해야 한다.
1. Path Variable
2. Query String
3. Request Body
4. Request Header
사실, 위 4개 중 API Endpoitn (URI)에 직접 적으로 포함되는 것은 첫 번째 Path Variable 뿐이다.
포스팅 초반에 말했듯이 API 설계란,
RESTful API 등의 스타일을 정하고, URL 구조, HTTP 메서드, 요청/응답 포맷 등을 정의한다! 고 했다.
API EndPoint로 알 수있는 정보는 Http Method(역할) 와 말그대로 resource의 최종 도착지점 뿐이다.
💡 회원가입에 대한 고민
그렇다.... POST /users 로 끝인가?
회원 정보를 저장하는 거잖아!
무슨 정보를 저장하는데?
그리고 무슨 응답을 줄건데..?
여러 가지 정보가 누락되어 있다.
이런 경우 위 4가지를 사용하게 된다.
천천히 알아보자.
💡 Path Variable
게시글 하나 상세 조회 API 를 설계한다고 해보자.
1 건 조회??
이제 쉽게 GET 메소드를 떠올리게 될 것이다!
그런데, 어떻게 특정 게시글임을 서버에게 전달이 가능할까?
다시 말해, 서버에게 어떻게 원하는 게시글을 식별할 수 있는 데이터를 넘길 수 있을까?
이런 경우에 path variable을 사용한다.
단 하나, 특정 대상을 지목할 때
/users/articles/{userId} 처럼 id에 게시글의 식별 값을 넣어서 전달한다.
예시를 보자면,
GET https://tistory.com/users/articles/4
서버는 해당 {userId}로 4라는 숫자를 받으면,
서버는 데이터베이스 상에서 4번째 게시글의 기본키라는 것을 캐치할 수 있다.
실제 API 명세서에서는 아래처럼 표현한다!
🔑 GET /users/articles/{articleId}
{ }(중괄호)로 감싸는 부분은 path variable을 의미한다!
그냥 id 보다는 articleId처럼 더 명시적으로 표현해주는 것이 더 좋다.
규칙중 단어 구분을 -를 사용해서 한다 규칙이 있었다.
규칙상으로는
🔑 GET /users/articles/{article-id}
이 맞지만,
관용적으로
대부분 {articleId}의 형식으로 표현하는 것 같다.
🔑 GET /users/articles/{articleId}
💡 Query String
그렇다면 쿼리 스트링은 언제 사용되는가?
게시글 중에서 이름에 umc가 포함된 게시글들을 조회하려고 할 때!
이럴 경우, 하나가 아니라 여러 개가 될 수도 있다!
즉, id로 특정하여 하나만을 조회하지 못할 수 있다는 이야기다.
path variable 사용하기 어렵다...
이럴 때 Query String을 활용할 수 있다!
보통 쿼리 스트링은 "검색 조회" 때 사용 된다.
따라서 GET 요청에서만 사용하는 것이 규칙!
GET /users/articles?name=umc
또한, 여러 개의 정보를 전달하고 싶다면??
&를 활용하면 된다!
GET /users/articles?name=umc&owner=ddol
이런 형태는 많이 보았을 것이다!

예시로 해당 uri 도 어떻게 구성되어 있나 보자.
Host : ~~naver.com 부분 뒷 부분만 보자면,
경로 (Path): /search.naver 서버 내에서 요청을 처리할 리소스의 경로
이 경우에는 네이버 검색 엔진의 검색 기능을 받는 Endpoint이다.쿼리 파라미터 (Query Parameters):
- where=nexearch: 검색 영역을 지정한다.
- sm=top_sug.pre, fbm=0, acr=3, qdt=0 등의 파라미터 들이 &로 엮여 있다.
(의미는 몰라도 된당~ 형식만 보는중)
- acq=%EC%95%88%EB%85%95: 자동 완성 쿼리로, 한글 "안녕"이 URL 인코딩되어 있다.해당 URI는 네이버 검색 엔진에서 "안녕"이라는 검색어로 검색을 수행하는 요청을 나타낸다.
이 URI를 통해 클라이언트는 네이버 검색 서버에 "안녕"이라는 검색어에 대한 검색 결과를 요청하고,
서버는 해당 검색어에 대한 검색 결과를 반환할 것이다.


🚨주의 : 쿼리 스트링은 API 엔드포인트에 포함되지는 않기 때문에,
엔드포인트 자체에는 GET /users/articles 로 설계해야 하며
쿼리 스트링의 양식은 세부 사항이나, 예시 쪽에 써주는 것이 좋다.
💡 Request Body
POST는 실제 DB의 자원을 생성하는 메서드이다.
조회가 아닌 "생성"에 관한 메서드이기 때문에,
DB의 데이터를 변경할 수 있다는 점에서 매우 보안적으로 신경써야하는 부분이다.
즉, url에 resource들을 모두 노출시키는 것은 매우 좋지 않은 설계이다.
따라서, url에 노출시키지 않고, request body에 해당 데이터를 담을 수 있다.
형태는 Json 형식 혹은 Form-data 형식이 있다.
RESTful API의 경우, JSON 형식을 주로 사용한다!
JSON은 데이터 교환에 있어서 경량화되고 읽기 쉬운 형식으로 사용되고 있다.
다만, 파일 업로드와 같은 바이너리 데이터 전송이 필요한 경우에는 Form-data 형식이 사용된다.
사실 웹 브라우저에서 기본적으로 지원하는 형식은 form-data라는 것...
어쨌든, 회원가입의 정보를 request body에 담아서 json 형식으로 서버에 전송한다면, 다음 형식으로 보낼 수 있다.
{
“name” : “김진호”,
“phoneNum” : “010-1111-2222”,
"nickName" : "ricky",
}
💡 Request Header
마지막 Header이다.

'뭐야? "목적지(EndPoint)"에 정확한 내용물(Json)을 박스(RequestBody)에 담아서 보내면 끝나거 아냐?'
뭘 또 해야하나....
하지만 하나 빠뜨린게 있는듯 한데...?
바로 "송장"!

그 박스를 목적지까지 무사히 전달하려면 몇 가지 추가 정보가 필요할 겁니다.
예를 들면...
내용물이 무엇인지 (Content-Type)
박스의 크기는 어느 정도인지 (Content-Length)
박스를 받는 사람은 누구인지 (Host)
박스를 보내는 사람은 누구인지 (User-Agent)
등등...
이러한 추가 정보들이 바로 Request Header에 해당한다.
Request Header는 마치 박스에 붙이는 송장이나 라벨 같은 역할을 한다고 생각하면 편할 것 같다.
✒️ 7. API 설계 예시
예를 들어 닉네임 변경(사용자 정보 변경) API에 대한 설계를 한다고 가정해보자.
아래와 같은 정보를 명시할 수 있다.
💡 API EndPoint
PATCH /users/{userId}
💡 Request Body
{
"nickname" : "ddol"
}
💡 Request Header
Authorization : accessToken (String)
accessToken은 로그인 된 사용자가 나 로그인 된 상태야! 하고 인증해주는 것으로
(회사 문 통과할 때 쓰는 키 정도로 생각)
보통 Authorization이라는 키에 대한 값으로 헤더에 담아서 서버로 보내주게 된다.
(Filter에서 인증 통과하면 "너 인정!" 외치고 들여보내준다.)
💡 Query String
현재는 필요 없음
✒️ 8. 프로젝트 세팅하기
💡 Spring Boot - 추가자료
프로젝트 세팅 하는 글은 내 포스팅에도 많고, 구글링해도 너무 많이 나와서 생략한다..
1. 통신
HTTP/HTTPS 통신 & RESTful API
1. HTTP/HTTPS 통신 웹 브라우저와 웹 서버 간의 통신은 주로 HTTP(또는 HTTPS) 프로토콜을 사용한다. 1) HTTP/HTTP HTTP(Hyper Text Transfer Protocol) 란? 클라이언트(웹 브라우저)가 서버에 요청을 보내고, 서버가
jinhos-devlog.tistory.com
2. JSON
JSON이란?
1. JSON이란? JSON(JavaScript Object Notation)은 데이터 교환을 위한 경량의 데이터 교환 형식이다. (XML과 같은 다른 형식도 있다.) JSON은 인간이 읽고 쓰기 쉽고, 기계적으로 파싱하고 생성하기도 쉽다는
jinhos-devlog.tistory.com
3. JAVA를 공부하기 전에 알두면 좋을 것들
0. JAVA를 공부하기 전에 알두면 좋을 것들
다음은 글은 infrean의 "자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]" 강의의 학습 목적으로 작성된 것입니다. 강의의 디테일한 내용
jinhos-devlog.tistory.com
4. 프로젝트 세팅 / API 만들기
1. API 만들기
다음은 글은 infrean의 "자바와 스프링 부트로 생애 최초 서버 만들기, 누구나 쉽게 개발부터 배포까지! [서버 개발 올인원 패키지]" 강의의 학습 목적으로 작성된 것입니다. 강의의 디테일한 내용
jinhos-devlog.tistory.com
5. Spring Initializr에서 Gradle-groovy와 -Kotlin의 차이
Spring Initializr에서 Gradle-groovy와 -Kotlin의 차이
Gradle은 빌드 자동화 도구이며, Groovy와 Kotlin 두 가지 언어를 사용하여 빌드 스크립트를 작성할 수 있다. 이전에는 다음과 같이 Gradle과 Maven으로만 빌드 툴이 나누어져 있었다면, 최근에는 Groovy와
jinhos-devlog.tistory.com