-
HTTP 웹 기본 지식 4편CS/네트워크 2024. 12. 2. 12:37
API (Applicaiton Programmin Interface)
- 클라이언트와 서버간의 상호 작용을 위한 인터페이스이다.
- 데이터를 주고 받거나 기능을 호출하거나 특정 작업을 수행할 수 있도록 접근 가능한 경로를 제공한다.
- 복잡한 내부 로직을 숨기고, 간단한 호출로 필요한 기능을 사용할 수 있다.
- 예를 들어, 자동차의 엔진 구조를 몰라도, 운전자는 페달만 밞으면 된다.
API URI 설계
- 회원 목록 조회: /read-member-list
- 회원 조회: /read-member-by-id
- 회원 등록: /create-member
- 회원 수정: /update-member
- 회원 삭제: /delete-member
처음 API URI를 위와 같이 설계했다고 하자. 직관적으로 이해가 잘된다. 하지만 이것이 좋은 URI 설계일까?
URI 설계에서 가장 중요한 것은 "리소스 식별" 이다. 그렇다면 리소스의 의미는 "무엇"일까?
- 리소스는 회원을 등록하고 수정하고 조회하는 게 리소스가 아니다. read, create,...
- 회원이라는 개념 자체가 바로 리소스이다. member
- 그렇다면, "어떻게" 리소스를 식별하는 게 좋을까?
- 회원을 등록하고 수정하고 조회하는 것을 모두 배제. 즉, URI에서 read, create,.. 를 없얘자.
- 회원이라는 "리소스"만 식별하면 된다. -> 회원 리소스를 URI에 매핑한다.
- 맨 처음 API URI를 다시 설계 해보자.
- 회원 목록 조회: /members
- 회원 조회: /members/{id}
- 회원 등록: /members/{id}
- 회원 수정: /members/{id}
- 회원 삭제: /members/{id}
참고: 계층 구조상 상위 컬렉션으로 보고 복수 단어 사용 권장 ( member -> members)
여기서 의문 !! 같은 URI인데 어떻게 “조회”, “등록”, “수정” 그리고 “삭제” 임을 구분할까?
-> HTTP method 로 구분한다.
리소스와 행위를 분리. 가장 중요한 것은 리소스를 식별하는 것.
URI는 리소스만 식별 !
리소스와 해당 리소스를 대상으로 하는 행위를 분리
리소스: 회원 행위: 조회, 등록, 수정, 삭제
리소스는 명사, 행위는 동사(미네랄을 캐라)
행위(메서드는) 어떻게 구분?HTTP method 종류
GET
GET /search?q=hello&hl=ko HTTP/1.1 host: www.google.com
- 리소스를 조회한다.
- 서버에 전달하고 싶은 데이터는 query(쿼리 스트링, 쿼리 파라미터)를 통해서 전달한다.
- 메시지 바디를 통해서 데이터를 전달할 수 있지만, GET method의 바디를 잘 처리 안하는 서버들이 많기 때문에 권장하지 않는다.
- 클라이언트가 서버에 HTTP 요청을 한다.
- GET (리소스 조회를 원한다.)
- 뭐에 대한 조회?? /memebers/100 리소스 조회 요청
- HTTP 는 stateless니깐 이렇게 한 번에 요청을 줘버리는 거야. 누구든(서버) 할 수 있겠지?
- 서버는 그에 대한 정보를 찾고 클라이언트에 응답을 보낸다.
POST
POST /memebers HTTP/1.1 Contetn-Type: application/json { "username": "kim", "age": 20 }
- 클라이언트가 HTTP 서버에 HTTP 요청을 한다.
- 이 때, 메시지 바디를 통해 서버로 요청 데이터를 전달한다.
- 여기서 URI를 잘 보면 리소스의 위치를 알지 못한다. 당연하다. 신규 생성이니깐.
- 서버는 요청 데이터를 처리한다. -> 신규 리소스 생성
- 메시지 바디를 통해 들어온 데이터를 처리하는 모든 기능을 수행한다.
- 주로 전달된 데이터로 신규 리소스 등록, 프로세스 처리에 사용한다.
POST 요청 데이터를 어떻게 처리한다는 뜻일까?
- 스펙에 따르면 POST method 대상 리소스가 리소스의 고유한 의미 체계에 따라 요청에 포함된 표현을 처리하도록 요청한다.
- 예를 들어, HTML form에 입력된 필드와 같은 데이터 블록을 데이터 처리 프로세스에 제공
- form에 입력한 정보로 회원 가입, 주문 등에서 사용
- 게시판, 뉴스 그룹, 블로그 또는 유사한 기사 그룹에 메시지 게시
- 예를 들어, 게시판 글쓰기와 댓글 달기
- 서버가 아직 식별하지 않은 새 리소스 생성
- 예를 들어, 신규 주문 생성
- 기존 자원에 데이터 추가
- 예를 들어, 한 문서 끝에 내용 추가하기
이 리소스 URI에 POST 요청이 오면 요청 데이터를 어떻게 처리할지 리소스마다 따로 정해야함.
즉, 정해진 것이 없는 method임이 분명하다...POST 정리하자면....
- 새 리소스 생성 (등록)
- 서버가 아직 식별하지 않은 새 리소스를 생성할 때 사용된다.
- 요청 데이터 처리
- 단순히 데이터를 생성하거나, 변경하는 것을 넘어서 "프로세스"를 처리해야 하는 경우
- 예를 들어, 주문에서 결제완료 -> 배달 시작 _> 배달 완료 처럼 단순히 값 변경을 넘어 프로세스의 상태가 변경되는 경우
- 위 과정은 단순히 "값 변경" 이상의 작업이다. 시스템의 여러 작업이 유기적으로 연결된 상태 전환을 포함하므로, 이를 프로세스 상태가 변경된다고 할 수 있다. 따라서 이럴 때 POST를 사용한다.
- POST 의 결과로 새로운 리소스가 생성되지 않을 수도 있다.
- 예를 들어, POST /orders/{ordersId}/start-delivery, control-URI
- 우리는 분명히 위에서 리소스와 행위를 구분해야 된다고 했지만, 실무에서는 항상 그렇게 이상적일 수는 없다. 그럴 때 리소스와 행위를 같이 써야 한다. 그런 URI를 컨트롤 URI 라고 한다.
- 단순히 데이터를 생성하거나, 변경하는 것을 넘어서 "프로세스"를 처리해야 하는 경우
- 다른 메서드로 처리하기 애매한 경우
- 예를 들어, JSON 으로 조회 데이터를 넘겨야 하는 데, GET 메서드를 사용하기 어려운 경우 POST를 사용한다.
참고: 조회할 때는 GET이 유리하다. 왜냐면 캐싱을 할 수 있기 때문이다. 스펙에는 POST도 캐싱이 가능하다고 하지만, 실무에서는 POST로 캐싱할 경우 body의 내용도 키 값을 가져야 하기 때문에 구현에 어려움이 있다. GET의 경우 URI 가 키 값이므로 쉽게 할 수 있다.
PUT
- 리소스가 있다면, 리소스를 완전히 대체한다.
- 쉽게 이야기해서 파일이 있으면 덮어버리잖아. 그런 느낌.
- 리소스가 없다면, 리소스를 생성한다.
- 중요 ! 클라이언트가 리소스를 식별한다.
- POST의 경우 POST /members 만 했자나.
- PUT의 경우 PUT /members/100 처럼 리소스의 위치를 알고 URI를 지정한다.
PUT /members/100 HTTP/1.1 Content-Type: application/json { "username": "old", "age": 50 }
- 위는 클라이언트가 요청한 것이고. 아래는 현재 서버에 들어 있는 데이터라고 하자.
{ "username": "young", "age": 20 }
- 만약에 성공적으로 PUT이 된다면 서버에 있는 데이터는 요청 보낸거로 바뀔 것이다.
- 그리고 아까 완즈니 덮어 버린다고 했잖아요. 만약 클라이언트가 요청을 보낼 때
PUT /members/100 HTTP/1.1 Content-Type: application/json { "age": 50 }
- 이렇게만 보낸다면, 서버에 뭐가 저장되어 있는 지간에 age에 대한 정보만 남을 것이다.
- 만약 리소스가 없는 경우에는 신규 리소스를 생성하겠지?
- 근데 여기서 의문이 리소스의 존재 여부를 알지 못할 때, 덮어쓰기를 방지하는 방법이 있을까?
- 조건부 요청: If-None-Match 헤더 사용한다. 그리고 POST와 PUT을 명확히 사용한다.
PATCH
- PUT은 부분만 변경할 수 없다. 따라서 PATCH를 사용하면 부분만 요청해도 부분만 수정할 수 있다.
DELETE
- 리소스 제거
HTTP method의 속성
- 안전 (Safe Methods)
- 호출해도 리소스를 변경하지 않는다.
- 예를 들어, GET으로 조회하는 데 리소스를 변경하겠는 가? 아니다 !! 단순 조회자나
- 다른 예로, GET 외에 다른 method(POST, DELETE, PATCH, PUT)은 리소스를 변경한다는 의미에서 안전하지 않다.
- 만약 계속 호출해서 로그 같은 게 쌓여서 장애가 발생하면? 안전은 해당 리소스만 고려한다. 그런 부분까지 고려하지 않는다.
- 멱등(Idempotent Methods)
- 한 번 호출하든 두 번 호출하든, 100번 호출하든 결과가 똑같다.
- 예를 들어
- GET: 한 번 조회하나 여러 번 조회하나 결과는 똑같다.
- www.naver.com 들어갔는 데 매번 다르니? 물론 그 안에 데이터 생각 말고 갑자기 구글에 접속되진 않자나
- PUT: 결과를 대체한다. 따라서 같은 요청을 여러 번 해도 최종 결과는 같다.
- DELETE: 결과를 삭제한다. 같은 요청을 여러 번해도 삭제된 결과는 똑같다.
- POST: 멱등이 아니다. 두 번 호출하면 같은 결제가 중복해서 발생할 수도 있다.
- GET: 한 번 조회하나 여러 번 조회하나 결과는 똑같다.
- 이 멱등을 도대체 어디에서 활용할까?
- 자동 복구 메커니즘에서 활용된다.
- 예를 들어, 서버가 TIMEOUT 등으로 정상 응답을 못 주었을 때, 클라이언트가 같은 요청을 다시 해도 되는 가? 에 대한 파단 근거가 되어줄 수 있다.
- 쉽게 말해 GET 요청ㅇ을 했는 데, 정상 응답을 못 주었어. 그러면 자동 복구 메커닞므에 의해 다시 GET 요청을 해도 GET은 "멱등" 이기 때문에 다시 해도 문제가 없다. 더 쉽게 말해서 Google Chrome 응용 프로그램이 예기치 않게 종료되었습니다. 에서 복구하는 버튼에서 멱등이 활용되지 않을까? (내 생각임)
- 멱등은 외부 요인으로 중간에 리소스가 변경되는 거까지 고려 하지 않음.
- 예를 들어,
- GET 조회를 하고
- 근데 PUT 으로 데이터가 바뀌었어..
- GET 하면 바뀐 데이터가 조회 되겠지. 그건 고려 하지 않음.
- 캐시 가능(Cacheable Methods)
- 응답 결과 리소스를 캐시해서 사용해도 되는 가?
- 웹 브라우저에 큰 요청을 했잖아. 다시 서버에 요청하면 오래 걸리잖아. 로컬 PC에 저장하고 있을 수 있냐 없냐
- GET, HEAD, POST, PATCH 캐시 가능하지만 실제로는 GET, HEAD 정도만 캐시로 사용한다. 그 이유는 그 외 메서드는 본문 내용까지 캐시 키로 고려해야 하는 데, 구현이 쉽지 않기 때문이다.
- 응답 결과 리소스를 캐시해서 사용해도 되는 가?
'CS > 네트워크' 카테고리의 다른 글
HTTP 웹 기본 지식 3편 (0) 2024.12.01 HTTP 웹 기본 지식 2편 (2) 2024.12.01 HTTP 웹 기본 지식 1편 (1) 2024.12.01 [네트워크] 클라이언트 - 서버 모델 (2) 2024.10.31 Socket, Port, TCP connection 개념 (0) 2024.05.22