매개변수(parameter)와 전달인자(argument)

|

종종 매개변수(parameter)와 전달인자(argument)는 적당히 섞어서 쓰이기도 하는데, 이 경우 문맥에 따라 의미를 달리해서 해석되기도 한다. 하지만 엄밀히 말해서 매개변수는 함수의 정의부분에 나열되어 있는 변수들을 의미하며, 전달인자는 함수를 호출할때 전달되는 실제 값을 의미한다. 이같은 의미를 명확히 하기 위해 매개변수는 변수(variable)로, 전달인자는 값(value)으로 보는 것이 일반적이다.

매개변수는 함수의 정의 부분에서 볼 수 있으며, 전달인자는 함수를 호출하는 부분에서 볼 수 있다. f(x) = x*x와 같은 함수 정의 부분에서 변수 ‘x’가 매개변수가 되며, f(2)와 같은 함수 호출 부분에서 값 ‘2’ 가 함수의 전달인자가 된다.

각각의 매개변수는 함수의 정의 부분에 포함되어 있는 고유한 특성이다. 예를 들어, (대다수의 언어에서는) 입력으로 들어온 2개의 정수를 더해서 합을 계산해 주는 함수의 경우 정수 형태의 매개변수 2개가 필요하다. 일반적으로 함수는 몇개의 매개변수를 가지든 상관없으며, 매개변수가 하나도 없을 수도 있다. 만약 함수가 매개변수를 가질 경우, 각각의 매개변수에 대한 정의를 나열해 놓은 것을 매개변수 목록(parameter list) 이라고 한다.

반면 전달인자는 함수가 호출될때 제공되는 값들을 말하며, 함수 정의의 한 부분으로 바뀌지 않는 매개변수와는 달리 호출 할 때마다 값이 바뀔 수 있다. 함수를 호출하는 부분에서 전달인자를 나열해 놓을 것을 전달인자 목록(argument list) 이라고 한다.

# parameter (매개변수)
# 함수의 정의 부분에 나열되어 있는 변수, 여기서는 plus 함수 정의시에 사용되는 a, b를 parameter(매개변수) 라고 한다.
def plus(a, b):
  return a + b

# argument (전달인자)
# 함수를 호출할때 전달 되는 실제 값, 여기서는 plus 라는 함수에 넣어주는 값 1, 2를 argument(전달인자)라고 한다.
result = plus(1, 2)

update_fields - 어떤 필드를 저장할지 지정하기

|

만약 save() 메소드 호출시에 update_fields 라는 키워드 인자로 필드 이름 리스트가 함께 전달 된다면, 해당 필드 목록만 업데이트 될 것이다. 당신이 하나의 필드 혹은 몇개의 필드만 업데이트 하려고 할 때 유용하게 사용될 수 있다. 그리고 DB의 모든 모델 필드가 업데이트 되는걸 막음으로써 약간의 성능적인 이점도 있다.

product.name = 'Name changed again'
product.save(update_fields=['name'])

update_fields 전달인자는 모든 반복가능한 문자열을 포함할 수 있다. update_fields=[]와 같이 빈 update_fields를 포함하면 save 메소드는 아무것도 수행하지 않고 생략된다. update_fields=None 의 경우에는 모든 필드에 대해서 업데이트를 수행한다.

update_fields를 지정함으로써 업데이트를 강제할 수 있다.

지연 모델 로딩(only() 혹은 defer())을 통해서 가져온 모델을 저장할때, DB로부터 로딩된 필드만 업데이트 된다. 사실상 이 경우 자동 update_fields 가 지정된다. 만약 당신이 지연된 필드에 새로운 값을 지정하거나 수정을 한다면, 해당 필드는 updated fields에 자동으로 지정될 것이다.

(번역) RESTful API Designing guidelines — The best practices

|

RESTful API Designing guidelines — The best practices 번역글 입니다.

views


Facebook, Google, Github, Netflix와 같은 거대한 테크기업은 API를 통해서 개발자들과 프로덕트들이 자신들의 데이터를 사용할 수 있도록 하고, 그들을 위한 플랫폼이 되었다. 비록 당신이 다른 개발자들과 프로덕트를 위한 API를 개발하고 있지 않더라도, 잘 만들어진 API를 갖고 있는 것은 당신의 어플리케이션을 위해서도 좋다.

인터넷에서는 오랫동안 API 디자인을 위한 가장 좋은 방법에 대해서 논의가 이루어졌다. 하지만 통일된 공식적인 가이드라인은 없다.

API는 많은 개발자들이 데이터와 상호작용을 하기 위한 인터페이스이다. 잘 디자인된 API는 사용하기 쉽고, 개발자들의 삶을 편하게 만들어준다. API는 개발자를 위한 GUI이며, 만약 사용하기 혼란스럽거나 설명이 부족하다면 개발자들은 대체물을 찾아서 떠날 것이다. 개발자 경험은 API의 질을 측정함에 있어서 가장 중요한 기준이라고 할 수 있다.


views
API는 무대에서 공연하는 아티스트이고, 사용자는 관객이다.

1) 용어

다음은 REST API에 관련된 가장 중요한 용어들이다.

  • Resource 는 어떤 것의 대표 혹은 객체이다. 이는 관련 데이터를 갖고 있고, 이를 운용하기 위한 메소드 집합을 가질 수 있다.
    예: Animals, schools, employees는 resources이고 delete, add, update는 이 resources들에서 수행되는 operations이다.
  • Collections 는 resources의 집합이다.
    예: Companies는 Company resource의 집합니다.
  • URL (Uniform Resource Locator)은 어느 resource가 어디에 위치할 수 있고, 어떤 action들이 수행될 수 있는지를 나타내는 경로이다.

2) API endpoint

더 이해하기 위해서 Employees를 가진 Companies에 대한 API를 작성해보자. /getAllEmployees 는 employees의 리스트를 response하는 API이다. Company에 관련된 API는 다음과 같은 것이 존재할 수 있다.

  • /addNewEmployee
  • /updateEmployee
  • /deleteEmployee
  • /deleteAllEmployees
  • /promoteEmployee
  • /promoteAllEmployees

그리고 다른 operations을 위해서 아주 많은 API endpoints가 존재할 수 있다. 이는 많은 중복을 포함하고 있고, 이러한 API endpoints는 수가 증가함에 따라서 유지보수가 힘들어진다.

무엇이 문제일까?

URL은 오직 resources(명사)만 포함해야 하며 동사나 actions를 포함해서는 안된다. API path /addNewEmployee 는 action 인 addNew 를 resource 이름은 Employee와 함께 포함하고 있다.

그럼 무엇이 올바른 방법일까?

/companies endpoint는 action을 포함하지 않는 좋은 예시이다. 그럼 이럴 땐 어떻게 서버에게 해당 companies resource에 대해서 add, delete, update와 같은 actions을 수행하도록 알려줄 수 있을까?

이는 동사인 HTTP 메소드 (GET, POST, DELETE, PUT)가 그 역할을 수행할 수 있다.

resource는 언제나 API endpoint에서 복수형 이어야 한다. 그리고 만약 resource의 특정 인스턴스에 접근하고 싶다면 URL에 id를 전달하여 접근할 수 있다.

  • method GET path /companies 는 companies의 모든 목록을 가져온다.
  • method GET path /companies/34 는 company 34의 상세 내용을 가져온다.
  • method DELETE path /companies/34 는 company 34를 삭제한다.

몇 가지 다른 사용 사례에서 resource 아래에 여러 개의 resources가 있는 경우 (예 : 회사의 직원들), API endpoint는 아래와 같을 수 있다.

  • GET /companies/3/employees 는 company 3에 속하는 employees 전체 목록을 가져온다.
  • GET /companies/3/employees/45 는 company 3에 속하는 employee 45의 상세 내용을 가져온다.
  • DELETE /companies/3/employees/45 는 company 3에 속하는 employee 45를 삭제한다.
  • POST /companies 는 새로운 company를 생성하고, 생성된 company의 상세 내용을 리턴한다.

이와 같은 API가 더 일관성 있고 정확하지 않은가?

결론: path는 resources의 복수형을 포함해야 하고, HTTP 메소드는 해당 resource를 대상으로 수행되는 action의 종류를 정의해야 한다.

3) HTTP methods (동사)

HTTP는 resources를 대상으로 수행할 수 있는 몇 가지 타입의 methods를 정의해두고 있다.

URL은 문장이고, resources는 명사이며 HTTP methods는 동사이다.

주요 HTTP methods 는 아래와 같다.

  1. GET method는 resource로 부터 데이터를 요청하며, 어떤 side effect도 발생시켜서는 안 된다.
    예: /companies/3/employees 는 company 3에 속하는 모든 employees를 리턴한다.

  2. POST method는 database에 resource를 생성하도록 서버에 요청하며, 대부분 web form 형식으로 제출된다.
    예: /companies/3/employees 는 company 3에 새로운 employee를 생성한다.
    POST는 멱등성을 갖지 않으며 여러번의 request는 각각 다른 영향을 미친다.

  3. PUT method는 resource를 업데이트 하거나, 만약 존재하지 않는 경우 생성하도록 서버에 요청한다.
    예: /companies/3/employees/john 는 company 3에 속하는 employees collection에 john이라는 resource를 업데이트하거나 생성하도록 서버에 요청한다.
    PUT은 멱등성을 가지며, 여러 번의 request는 같은 영향을 미친다.

  4. DELETE method는 resources 혹은 그것의 인스턴스를 database에서 삭제하도록 요청한다.
    예: /companies/3/employees/john/ 는 company 3에 속하는 employees collection에서 john이라는 resource를 삭제하도록 서버에 요청한다.

4) HTTP response status codes

API를 통해서 클라이언트가 서버에 request를 발생시키면 클라이언트는 해당 request가 성공, 실패 혹은 request 자체가 잘못되었는지 등의 결과를 얻을 수 있어야 한다. HTTP status code는 다양한 시나리오에서의 상황을 설명할 수 있는 표준화된 코드이다. 아래는 HTTP 코드의 주요 카테고리 분류이다.

2xx (Success Category)

해당 status code 들은 request가 정상 수신되고 서버를 통해서 성공적으로 수행되었음을 나타낸다.

  • 200 Ok GET, PUT, POST 성공을 대표하는 표준 HTTP response
  • 201 Created 해당 status code는 새로운 인스턴스 생성 시 리턴되어야 한다. 예를 들면 POST 메소드를 사용하여 새로운 인스턴스가 생성되면 항상 201 status code를 리턴한다.
  • 204 No Content 는 request가 성공적으로 수행되었으나 아무것도 리턴되지 않음을 의미한다. 대표적인 예로 DELETE가 있다. API DELETE /companies/43/employees/2 는 employee 2를 삭제하고 리턴되는 API response body에는 아무런 데이터도 필요하지 않다. 이는 시스템에 명시적으로 삭제하도록 요청했기 때문이다. 만약 employee 2가 데이터베이스에 존재하지 않는 것과 같은 에러가 발생한다면, 2xx Success Category 가 아닌, 4xx Client Error category response code를 리턴하게 된다.

3xx (Redirection Category)

  • 304 Not Modified 는 client가 해당 response를 이미 캐시로 갖고 있음을 의미한다. 따라서 같은 데이터를 다시 전달할 필요가 없다.

4xx (Client Error Category)

아래의 status code들은 client가 잘못된 request를 전달했음을 의미한다.

  • 400 Bad Request 는 client의 요청사항을 서버가 이해하지 못해서 request가 정상적으로 수행되지 않았음을 의미한다.
  • 401 Unauthorized 는 client가 resources에 대한 접근 권한이 없으며 필요한 자격을 갖추고 다시 request 해야 함을 의미한다.
  • 403 Forbidden 는 request가 유효하며, client의 권한에도 문제가 없지만 어떠한 이유로 인해서 client가 resource 페이지에 접근할 수 없음을 의미한다. 예를 들어 때때로 인증된 client가 서버의 디렉토리에 접근할 수 없는 경우가 있다.
  • 404 Not Found 는 요청된 resource가 현재 사용 불가능 함을 의미한다.
  • 410 Gone 는 요청된 resource가 의도적으로 이동되어 더 이상 사용 불가능 함을 의미한다.

5xx (Server Error Category)

  • 500 Internal Server Error 는 request가 유효하지만, 서버에 문제가 발생하여 예상치 못한 조건을 제공하도록 요청받았음을 의미한다.
  • 503 Service Unavailable 는 서버가 다운되거나 request를 처리할 수 없음을 의미한다. 대부분 서버 점검시에 발생한다.

5) 필드 네이밍 컨벤션

원하는 네이밍 컨벤션을 사용할 수 있지만, 어플리케이션 전체에 걸쳐서 일관성을 갖는 것이 중요하다. 만약 request body 혹은 response type이 JSON이라면 일관성을 위해서 카멜케이스 규칙을 따르는 것이 좋다.

6) 검색, 정렬, 필터링, 페이지네이션

이러한 모든 작업은 하나의 데이터 집합에 대한 쿼리일 뿐이다. 이 같은 action을 처리하기 위한 별도의 API set은 존재하지 않는다. 다만 API의 GET 메소드에 쿼리 파라미터를 추가 할 필요가 있다. 몇가지 예시를 통해서 해당 action 들을 어떻게 구현할 수 있는지 살펴보자.

  • Sorting 정렬된 companies 리스트를 원하는 경우, GET /companies endpoint는 여러개의 정렬 매개변수를 쿼리에서 받아야 한다. 예를 들어 GET /companies?sort=rank_asc 는 rank 오름차순으로 companies를 정렬해야 한다.
  • Filtering 데이터셋 필터링을 위해서 쿼리 매개변수를 통해 다양한 조건을 전달할 수 있다. 예를 들어 GET /companies?category=banking&location=india 는 india에 위치하는 banking 카테고리의 companies를 필터링해야 한다.
  • Searching companies list 중에서 이름을 검색하려면 API endpoint는 GET /companies?search=Digital Mckinsey 와 같아야 한다.
  • Pagination 데이터셋이 너무 큰 경우, 데이터를 작은 덩어리로 나눔으로써 퍼포먼스를 향상시키고 response 핸들링을 좀 더 편하게 할 수 있다. 예를 들어 GET /companies?page=23 은 companies 리스트의 23번째 페이지를 의미한다.

만약 GET 메소드에 많은 쿼리 매개변수를 전달하여 URI가 너무 길어진다면 서버는 414 URI Too long HTTP status를 응답할 것이다. 이런 경우에는 POST 메소드의 request body를 통해서도 매개변수를 전달할 수 있다.

7) Versioning

당신의 API가 여러 곳에서 사용되고 있을 때 일부 변경 사항으로 API를 업그레이드하면, 기존의 API를 사용하는 제품이나 서비스에 문제가 발생할 수 있다.

http://api.yourservice.com/v1/companies/34/employees 처럼 경로에 API의 버전을 포함하는 것은 좋은 예시이다. 만약 주요 업데이트가 있는 경우에는 v2, v1.x.x 와 같은 새로운 API set을 위한 이름을 사용할 수 있다.

2017년 11월 돌아보기

|

1

블로그를 좀 더 가벼운 마음으로 사용해야겠다는 생각을 한다. 그동안은 글을 하나 올리려고 해도 격식을 차리고 길게 써야한다는 부담이 있었다. 앞으로는 한줄짜리 글이라도 편하게 올려야지 (이렇게 아무말 대잔치 블로그가 되어가고..) 뭐 누군가에게는 도움이 되겠지!

2

여동생과 처음으로 둘이서 여행을 다녀왔다. 항공권, 숙소, 버스 예약부터 맛집 검색, 여행 계획 전부다 내가 준비했는데 오랜만에 언니 노릇을 한 것 같아서 뿌듯했다.

3

일본에 간김에 해피해킹 키보드를 사왔다. 나의 유일한 일본여행 쇼핑

views
알베르 까뮈의 섬 서문이 생각나는 사진이다. (길거리에서 이 조그만 책을 열어본 후 겨우 그 처음 몇 줄을 읽다 말고는 다시 접어 가슴에 꼭 껴안은 채 마침내 아무도 없는 곳에 가서 정신없이 읽기 위하여 나의 방에까지 한걸음에 달려가던 그날 저녁으로 되돌아가고 싶다.)

4

DRF + 리액트 강의를 결제하고 듣기 시작했다. 그동안 API가 뭔지 감이 안잡혔는데 강의를 들으니까 쉽게 이해가 가서 기분이 좋았다. DRF만 강의 갯수가 75개인데 짧아서 한번 듣고 또 한번 들었다. 덕분에 이번달도 휴대폰 데이터 폭탄 ㅠㅠ 이번에 다시 한번 느낀건 ‘나는 강의가 있어야 배울 수 있는 사람인가..ㅠㅠ’하는 점이다. DRF 같은 경우도 공식 홈페이지에서 문서를 보면서 몇번을 익혀보려고 시도했는데 모두 효과가 좋지 않았다. 근데 강의를 따라가면서 한번 쭉 실습해보니까 문서 볼때보다 훨씬 이해가 잘되서 놀랐다. 강의가 있어야만 이해할 수 있다는건 좋은 것 같지 않은데.. 걱정도 되고 다른 사람들은 어떻게 새로운걸 학습하는지 궁금하기도 하다.

5

DRF 여운이 가시기 전에 다시한번 혼자서 연습할지 리엑트로 진도를 나갈지 고민이다. 11월은 요것들 공부하는 재미로 보낸것 같다.

6

회사에 들어와서 처음으로 참여한 (본격) 프로젝트가 잘 마무리되었다. 좋은 선배님 덕분에 배운점도 느낀점도 많았다. 절묘하게 내가 할 수 있을 만한 일들이 (물론 나는 처음에 못할거라고 생각했다..) 적절하게 분배된 덕분에 재미도 있었다. 참 오랜만에 스스로 원해서 휴일에도 일하고 즐거웠다…후후후

7

벌써 12월이다. 벌써부터 약속들이 잡혀있는데 (파이썬 연말 세미나도 가기로 했다) 공부는 언제하지!

장고 쿼리셋 합치기

|

앞으로 가벼운 마음으로 블로그를 하기로 결심했으니 기념으로 짧은 글을 올려보자

쿼리셋 2개를 합치고 싶을때는 간단하게 |를 사용하면 된다. 대신 같은 모델에서 나온 쿼리셋만 합칠 수 있다.

q3 = q1 | q2
  • Django 1.11부터는 qs.union()메소드를 이용할 수 있다. 그 밖에도 쿼리셋간의 합집합, 교집합, 차집합을 만들 수 있는 메소드가 추가되었다. (intersection(), difference())
  • itertools.chain을 사용하는 방법도 있다.