Django์๋ ๋ฉ์ง etag/condition/last_modified ๋ฐ์ฝ๋ ์ดํฐ๊ฐ ์์ต๋๋ค. 'get'์ ์ฅ์ํ ์ ์๊ธฐ ๋๋ฌธ์ drf ํด๋์ค ๊ธฐ๋ฐ ๋ณด๊ธฐ์์๋ ์๋ํ์ง ์์ต๋๋ค. get์ http ์๋ต์ด ์๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๊ธฐ ๋๋ฌธ์ etag ํค๋๋ฅผ ์๋ต์ ์ถ๊ฐํ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
drf ๋ด์์ ์ด ์์ ์ ์ํํ๋ ๋ฐฉ๋ฒ์ ๋ณด๊ณ ์ถ์ต๋๋ค. ๋ฆฌ์์ค์ ๋ํ ์ฌ์ ์ ๊ฐ๋ฅํ ๋ฉ์๋ ๋๋ etag๋ฅผ ์์ฑํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ ๋ณด๊ธฐ(๋๋ ๋ฏน์ค์ธ)์ ๋ผ์ธ์ ๋ฐ๋ผ ์๊ฐํ๊ณ ์์ต๋๋ค.
django์์ ์ํํ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ๋ฏธ๋ค์จ์ด๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด์ง๋ง ๋ฐ์ฝ๋ ์ดํฐ์ฒ๋ผ ๋ทฐ์ ๋ณธ๋ฌธ ์คํ์ ๋จ์ถํ ์๋ ์์ต๋๋ค.
์, ์๋น ํจ์น๊ฐ ์์ต๋๋ค: https://github.com/schinckel/django-rest-framework/commit/cc3a88edc6be21347a9b35929d158b8831ba9bd3
๊ทธ๋ฌ๋ ์ด๊ฒ์ ๋ํ ํผ๋๋ฐฑ์ ๋ํด ๋งค์ฐ ๊ธฐ์๊ฒ ์๊ฐํฉ๋๋ค.
์ข์, ์ฒ์์ ๋ด๊ฐ ์ด ๊ฒ์ ์ด๊ฒ์ด์๋ค....
๋ฉ์ง๋ค์. ์ ๋ง ๋ณด๊ณ ์ถ์ต๋๋ค.
Coupla ์๊ฐ - ํ์ฌ ๊ฐ์ง๊ณ ์๋ View._ETAG๊ฐ ์๋ View.add_header๋ฅผ ์ฌ์ฉํ ์ ์์ด์ผ ํฉ๋๋ค.
(๊ทธ๋ฆฌ๊ณ .add_header๊ฐ ResponseMixin ํด๋์ค๋ก ์ฎ๊ฒจ์ ธ์ผ ํ ๊ฒ ๊ฐ์ต๋๋ค.)
๋์งธ, @condition , @etag ๋ฐ @last_modified ์ฅ์์ด https://github.com/django/django/blob/master/django/views/decorators ์ ์ง์ ์ ์ธ ๋ณต์ ๊ฐ ๋ ์ ์๊ธฐ๋ฅผ
ํ์ง๋ง ์กฐ๊ธ ๋ ์์ธํ ์ดํด๋ณด๋...
๊ทธ๋ฆฌ๊ณ ์๋ง๋ ์ด๊ฒ์ ๊ฒฐ๊ตญ ์ฌ๋ฐ๋ฅธ ๋ฐฉ๋ฒ์ด ์๋ ๊ฒ์ ๋๋ค...
REST ํ๋ ์์ํฌ ๋ณด๊ธฐ์์ ์ค์ ๋ก HttpResponses๋ฅผ ๋ฐํํ ์ ์์ง๋ง ์ผ๋ฐ์ ์ธ ์ฝํ
์ธ ํ์/์ง๋ ฌํ ํญ๋ชฉ์ด ๋ชจ๋ ์ ์ฉ๋์ง๋ ์์ต๋๋ค. @last_modified
, @etag
๋ฐ @condition
๋ฐ์ฝ๋ ์ดํฐ๋ ๋น HttpResponses๋ง ๋ฐํํ๋ฏ๋ก ์ค์ ๋ก ๋ฌธ์ ๊ฐ ๋์ง๋ ์์ต๋๋ค.
๊ทธ๋์ ๋ด๊ฐ ์๊ฐํ๋ ๊ฒ์ ๋จ์ํ __setitem__
__getitem__
๋ฐ has_header
๋ฅผ Response ํด๋์ค์ ์ถ๊ฐํ๋ฉด Django์ ๊ธฐ์กด @last_modified
๋ผ๊ณ ์๊ฐํฉ๋๋ค. @etag
๋ฐ @condition
๋ทฐ๊ฐ ์ฌ์ฉ as_ ์ฅ์์ด _so ์ค๋ REST ํ๋ ์ ์ํฌ๋ณด๊ธฐ์ ์ ์๋ํฉ๋๋ค return Response(status, data)
์คํ๋ ค๋ณด๋ค๋ ์คํ์ผ return data
์คํ์ผ์.
Obv ๊ทธ๊ฒ์ ๋ฌธ์ํํ๋ฉด ๋์์ด ๋ ๊ฒ์ด์ง๋ง Django๊ฐ ์ด๋ฏธ ์ํํ๋ ๊ฒ์ ๋ณต์ ํ๋ ๊ฒ๋ณด๋ค ๋ ํฉ๋ฆฌ์ ์ผ ์ ์์ต๋๋ค.
์ด๋ป๊ฒ ์๊ฐํด?
django ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ๋ฐ ํ ๊ฐ์ง ๋ฌธ์ ๊ฐ ์์ ์ ์์ต๋๋ค. ๋ฉ์๋์ ํจ๊ป ์๋ํ๋์ง ํ์ ํ ์ ์๊ณ ๋ฒ ์ด ๊ธฐ๋ฅ๋ง ์ฌ์ฉํ ์ ์์ต๋๋ค. ๋ด๊ฐ ์์ฑํ ๋ฐ์ฝ๋ ์ดํฐ๋ ์ด ๊ฒฝ์ฐ์๋ง StackOverflow๋ฅผ ํตํด ์ฐพ์ ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ํ์ต๋๋ค.
๊ทธ๋ ์ง ์์ ์๋ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ ์ด ์๋ฃจ์ ์ด ๋ ๋์ ๊ฒ ๊ฐ์ต๋๋ค.
๊ทธ๋ ๊ธด ํ์ง๋ง, ๋ ์์ฉ๊ตฌ์ด๊ธฐ ๋๋ฌธ์ ๋ฐํ ๋ฐ์ดํฐ ์คํ์ผ์ ๋ฐํํ๊ณ ์์ผ๋ฉฐ ์ผ๋ฐ์ ์ผ๋ก json์ผ๋ก ์ง๋ ฌํํ๋ ค๋ ๊ฐ์ฒด๋ง ๋ฐํํฉ๋๋ค. ์ฐ๋ฆฌ๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ์๋ํ๋๋ก ํ ์ ์์ต๋๋ค.
๋ ๋ค๋ฅธ ์ต์ ์ ์ด๋ฅผ View ํด๋์ค์ ์ถ๊ฐํ๋ ๋ฏน์ค์ธ์ผ ์ ์์ต๋๋ค.
๋ํ django ๋ฐ์ฝ๋ ์ดํฐ๊ฐ ์กฐ๊ฑด๋ถ PUT, POST ๋ฐ DELETE ์์ฒญ๊ณผ ๊ด๋ จํ์ฌ ์ฌ๋ฐ๋ฅธ ์์ ์ ์ํํ์ง ์์ ์๋ ์์ต๋๋ค. ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด sinatra์ ํจ์น๋ฅผ ์ ์ถํ์ต๋๋ค.
๋ง์ง๋ง ๋นํธ๋ฅผ ๋ฌด์ํ์ญ์์ค. ๋ถ๋ช ํ ์ ๋ ์ฝ๋๋ฅผ ์ ๋๋ก ์ฝ์ง ์์์ต๋๋ค.
์ค์ ๋ก ์์ ์ด ์์ต๋๋ค. ์ด๋ฌํ ๋ฐ์ฝ๋ ์ดํฐ๋ _methods_์์ ATM์ ์๋ํ์ง ์์ ์ ์์ต๋๋ค. ์ถ๊ฐ 'self' ์ธ์๊ฐ ์๊ธฐ ๋๋ฌธ์ ๋๋ค. ๋๋ ๊ทธ๊ฒ์ ์กฐ์ฌํ๊ณ poss๊ฐ Django์ ํฐ์ผ์ ์ ์ถํ ๊ฒ์ ๋๋ค. Django๋ CBV์ ํจ๊ป ์์ ํด์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋ค...
์, ์๊ฒ ์ต๋๋ค. ์ด์ https://docs.djangoproject.com/en/dev/topics/class-based-views/#decorating -class-based-views
๊ทธ๋์ ์ด๊ฒ์ ๋ซ์ผ๋ ค๋ฉด ๋ค์์ด ํ์ํ๋ค๊ณ ์๊ฐํฉ๋๋ค.
๋ถ๋ช ํ ๊ทธ ๋ฌธ์๋ฅผ ๋ณด์์ง๋ง ๊ทธ ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ๋ณด์ง ๋ชปํ์ต๋๋ค!
๋๋ django ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํ๊ณ ์ด๊ธฐ ๊ฒฐ๊ณผ๋ ์ ๋ง ์ด์ํ๊ณ , ๊ด๋ จ ์๋ etag ํจ์์ ๋ํ๋๋ ๋ทฐ์๋ง ์ํด์ผ ํ๋ ์ ๋ณด๊ฐ ์์์ต๋๋ค.
๊ทธ๊ฒ์ ์กฐ๊ธ ๋ ์ข๊ฒ ๋ง๋ค๊ธฐ ์ํด ๋ช ์๊ฐ ๋์ ๋ ธ๋ ฅํ ํ, ๋๋ ๋ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ์ถฉ๋ถํ ์ผ๋ฐ์ ์ผ๋ก ๋ณด์ด๋ ์๋ฃจ์ ์ ์๊ฐํด ๋์ต๋๋ค. ์ด์ ๋ํด ์ด๋ป๊ฒ ์๊ฐํ์ญ๋๊น?
https://bitbucket.org/vitormazzi/django-rest-framework/changeset/6f8de4500c6f
2.x ๋ฆด๋ฆฌ์ค๊ฐ ๋์จ ์ง๊ธ ์ด ๋ฌธ์ ์ ์๋ก์ด ์๋ช ์ ๋ถ์ด๋ฃ๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.
์ฌ๊ธฐ์์ ๋ด ์๊ฐ์ ๋๋ถ๋ถ ํ๋ก์ ํธ์ ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ ค๊ณ ์๋ํ๊ณ ์ด ๊ฒ์๋ฌผ ์ ์ฝ๋ ๊ฒ์์ ๋น๋กฏ๋ ๊ฒ์ ๋๋ค.
DRF๊ฐ ETag๋ฅผ ๊ณ ๋ คํด์ผ ํ๋ ๋ ๊ฐ์ง ์์ญ, ์ฆ ๋ทฐ์์์ ์ฌ์ฉ๊ณผ ์ธ์คํด์ค ๋ฒ์ ์ ๊ณ ์ ํ ํํ์ ์ป๋ ๋ฐฉ๋ฒ์ด ์์ต๋๋ค.
๊ฐ์ ธ ์ค๊ธฐ
GET ์์ฒญ์ ์ ์ ํ ํค๋์์ ๊ฐ์ฒด ETag๋ฅผ ์ ๊ณตํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. RetrieveModelMixin
๋ํ ํ ์ค ๋ณ๊ฒฝ์ ๋ค์์ ์ฝ๊ฒ ์ถ๊ฐํ ์ ์์ต๋๋ค.
def retrieve(self, request, *args, **kwargs):
self.object = self.get_object()
serializer = self.get_serializer(self.object)
headers = {'ETag': self.object.etag}
return Response(serializer.data, headers=headers)
๋ฃ๊ธฐ, ํจ์น, ์ญ์
HTTP ๋์ฌ ์
๋ฐ์ดํธ์ ๋ํ ์ผ๋ฐ์ ์ธ ํ์ธ์ ๋ณด๊ธฐ์ dispatch
ํ๊ฑฐ๋ ETag๊ฐ ์ผ์ ธ ์๋์ง ํ์ธํด์ผ ํ๋ฏ๋ก ๋ค๋ฅธ ๋ฉ์๋๋ก ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค(์๋ ์ต์
์น์
์ฐธ์กฐ).
header_etag = request.META.get('HTTP_IF_MATCH')
if header_etag is None:
return Response({'error': 'IF_MATCH header is required'}, status=400)
๊ทธ๋ฐ ๋ค์ ๊ฐ์ฒด๋ฅผ ๊ฒ์ํ ํ ์์ฒญ์ด ์ฌ๋ฐ๋ฅธ ๊ฐ์ฒด๋ฅผ ๋ณด๊ณ ์๋ค๊ณ ์๊ฐํ๋์ง ํ์ธํ๊ธฐ ์ํด ๋ ์์ธํ ํ์ธํฉ๋๋ค.
if self.object.etag != header_etag:
return Response({'error': 'object has been updated since you last saw it'}, status=412)
๋๋ ๊ฐ์ฒด์ ETag์ ์ค์ ์์ฑ์ด DRF์ ๋ฌธ์ ๊ฐ ๋์ด์ผ ํ๋ค๊ณ ์๊ฐํ์ง ์์ต๋๋ค. ๋ด ๊ฐ์ฒด์ updated
ํ๋์ ์ํฌํฌ ์๊ฐ์ ์ฌ์ฉํ์ฌ ํ
์คํธํ์ง๋ง ๋ ๋ณต์กํด์ผ ํจ์ ์ฝ๊ฒ ์ ์ ์์์ต๋๋ค.
์ ๋ DRF๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก obj.etag
๋ฅผ ์กฐํํ์ง๋ง get_etag()
๋ฐ etag_var = 'get_my_objects_etag'
์ ๊ฐ์ ์ผ๋ฐ CBV ํ๋ฆ์ ์ฌ์ฉํ์ฌ ๊ตฌ์ฑํ ์ ์๋ค๊ณ ์ ์ํฉ๋๋ค.
ํค๋์ ๋น๊ตํ๊ณ ์ ํ์ ํด์ํ๋ ค๋ ์๋๋ ๊ธฐ๊ปํด์ผ ๊ณ ํต์ค๋ฌ์ธ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ETag๊ฐ ๊ฐ์ฒด์์ ๋ฌธ์์ด๋ก ๊ฒ์๋๋๋ก ๊ฐ์ ํด์ผ ํฉ๋๋ค.
use_etags
(๋๋ ์ด์ ์ ์ฌํ ๊ฒ) - ๋ถ์ธetag_var
- ํด๋น ๊ฐ์ฒด์ ๋ํด getattr
ํ ์ ์๋ ํจ์ ์ด๋ฆ ๋ฌธ์์ด@ghickman - ETag ๋ฐ LastModified๋ฅผ ๊ฒฐ์ ํ๋ ๋์์ด ๋ค๋ฅธ ํ๋ฌ๊ทธํ ํด๋์ค์ ์ ์ฌํ๊ฒ ๋ณด์ด๋์ง ํ์ธํ๊ณ ์ถ์ต๋๋ค. ์ฆ. ๋ค์๊ณผ ๊ฐ์ ๊ฒ์ด ์์ต๋๋ค.
class MyView(views.APIView):
cache_lookup_classes = []
์บ์ฑ ์๋ช ์ ETag์ LastModified๋ฅผ ๋ชจ๋ ์ฒ๋ฆฌํด์ผ ํ๋ฉฐ ์ฐ๋ฆฌ๊ฐ ์ ๊ณตํ๊ณ ์ ํ๋ ๋ ๊ฐ์ง๊ฐ ์์ต๋๋ค.
BaseCacheLookup
์๊ณ ๋ค์๊ณผ ๊ฐ์ ๋ ๊ฐ์ง ๋ฉ์๋ ์๋ช
์ด ์์ต๋๋ค.
.object_etag_and_last_modified(self, view, obj)
.preemptive_etag_and_last_modified(self, view, request, *view_kwargs, **view_kwargs)
๊ฐ์ฒด๊ฐ
(etag, last modified)
์ 2-ํํ์ ๋ฐํํ๋ฉด ๋ ์ค ํ๋๋ ๋จ์ํ ์์์ผ ์ ์์ต๋๋ค.
๋ค์ด์ค๋ ์์ฒญ์ ์ผ์นํ๋ If-Modified-Since ๋๋ If-None-Match ํค๋๊ฐ ํฌํจ๋ ๊ฒฝ์ฐ 304 Not Modified ์๋ต์ด ๋ฐํ๋ฉ๋๋ค. ๋ค์ด์ค๋ ์๋ต์ ์ผ์นํ๋ If-Match ๋๋ If-Unmodified-Since๊ฐ ํฌํจ๋์ด ์์ผ๋ฉด 412 Precondition Failed ์๋ต์ด ๋ฐํ๋ฉ๋๋ค.
์ด๋ ๊ฒ ํ๋ฉด ์ค๋ช ํ ๊ตฌํ๊ณผ ์ผ์นํ๋ CacheLookupClass๋ฟ๋ง ์๋๋ผ ๋ค๋ฅธ ๋ณํ๋ ํ์ฉ๋ฉ๋๋ค.
์๋ฅผ ๋ค์ด, ๋ค๋ฅธ ๋ง์ง๋ง ์์ ์ธ๋ถ์ฑ์์ ์ฌ๋ฌ ์บ์ ์กฐํ ํด๋์ค๋ฅผ ์ ์ฉํ ์๋ ์์ต๋๋ค.
GlobalLastModifiedLookup
์ธ์ ObjectETagLookup
ํฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ์บ์๋ ๋ณต์ฌ๋ณธ ์ดํ์ ์ฐ๊ธฐ๊ฐ ์ํ๋์ง ์์ ๊ฒฝ์ฐ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํธ์ถ์ ์ํํ๊ธฐ ์ ์ ๋ทฐ๊ฐ ์ ์ ์ ์ผ๋ก ๋ฐํ๋ ์ ์์ต๋๋ค. (Varnish์ ํจ๊ป ์๋ฒ ์ธก ์บ์ฑ์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ ์ด์ ๊ฐ์ ์ ๋ง ๊ธฐ๋ณธ์ ์ธ ์ ์ฑ
์ด๋ผ๋ ์์ฒญ๋ ์ฐจ์ด๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค)
์ด ํ๋ฌ๊ทธ์ธ์ ํด๋์ค ์ธก๋ฉด์ด ํฉ๋ฆฌ์ ์ผ๋ก ๋ค๋ฆฝ๋๊น?
ํ์ฌ ๊ตฌํ์์ ์ฌ์ฉํ์ง ์๊ธฐ ๋๋ฌธ์ LastModified์ ๋ํด ์๊ฐํ์ง ์์์ง๋ง ์ฃผ์ด์ง ๋ชฉ์ ์ ๊ฐ์ํ ๋ ํฌํจํ๋ ๊ฒ์ด ํฉ๋ฆฌ์ ์ ๋๋ค.
Pluggable ํด๋์ค๋ ํนํ LastModified ๋ฐ ETag ๊ตฌํ์ ๊ธฐ๋ณธ ์์ ๋ก ํฌํจํ๋ ๊ฒฝ์ฐ ์ข์ ์์ด๋์ด์ฒ๋ผ ๋ค๋ฆฝ๋๋ค. ๋๋ GET ์บ์ฑ์ด ํ๋ก์ ํธ์ ๋ํ ์ต์ํ์ ๋ณ๊ฒฝ์ผ๋ก ๋งค์ฐ ์ฝ๊ฒ ์ผค ์ ์๋ค๋ ์์ด๋์ด๋ฅผ ์ข์ํฉ๋๋ค.
๋๋ etag์ last_modified ์์ฑ์ ๋น์ ์ด ์ ์ํ ๋๋ก ๊ตฌํ๋์ง ์์ ๋ None
๋ฐํํ๋ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ(๊ทธ ์ด๋ฆ ์ค)์ผ๋ก ๋ถํ ํ๋ ๊ฒ์ ์ ํธํฉ๋๋ค. ๊ทธ๋ฐ ๋ค์ CacheLookup ๋ฐฑ์๋๋ ํ๋ ๋ฐ/๋๋ ๋ค๋ฅธ ํ๋๋ฅผ ๊ตฌํํ๋๋ก ์ ํํ ์ ์์ต๋๋ค. ์ ์ฉํ๋ค๊ณ ์๊ฐ๋๋ฉด ๋ ๊ฐ์ง๋ฅผ ๊ฒฐํฉํ ํธ๋ฆฌํ ์ ํธ๋ฆฌํฐ ๋ฉ์๋( cachable_obj_repr
๋๋ unique_obj_repr
์๋ง๋?)๋ฅผ ํญ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
tl;dr ์, ํ๋ฌ๊ทธํ ํด๋์ค ์ธก๋ฉด์ ํฉ๋ฆฌ์ ์ผ๋ก ๋ค๋ฆฌ๊ณ ํจ์ฌ ๋ ํฐ ์ ์ฐ์ฑ์ ์ ๊ณตํด์ผ ํฉ๋๋ค. ์ด์ ๋ํ ํจ์น ์์ฑ์ ์์ํ๊ฒ ๋์ด ๊ธฐ์ฉ๋๋ค.
์ฌ๋ฌ๋ถ, ์๋ ํ์ธ์. ๊ด์ฌ์ด ์์ผ์๋ฉด ๋ด ํ์ฅ ๋ผ์ด๋ธ๋ฌ๋ฆฌ http://chibisov.github.io/drf-extensions/docs/ ์์ etag ์ง์์ ๋ํ ๋ค๋ฅธ ์ ๊ทผ ๋ฐฉ์์ ๊ตฌํํ์ต๋๋ค
@chibisov Neato. #1019๋ฅผ ๋๋ด์ผ ํ๋ฏ๋ก ๋ฌธ์ ์ด๋๊ฐ์ ์ด์ ๊ฐ์ ํจํค์ง์ ์ฐ๊ฒฐํ ์ ์์ต๋๋ค.
#1019๋ก ๋ซ๊ณ @chibisov ์ ํจํค์ง๊ฐ ๋์ด๋ฉ๋๋ค.
์ด๊ฒ์ ์ฐ๋ฆฌ๊ฐ ์ด๋ ์์ ์์ ์ด๊ฒ์ ๋ํ ๊ณต์์ ์ธ ์ง์นจ์ ์ ๊ณตํ๊ธฐ๋ฅผ ์ํ๊ธฐ ๋๋ฌธ์ ์๋์ ์ผ๋ก 3.3์ผ๋ก ์ด์ ํ๊ฐ ์ฐํ์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ์ด๊ฒ์ ๋ซํ ์ํ๋ก ๋๊ธฐ๋ก ์ ํํ๋๋ผ๋ ํฌ๊ฒ ๊ฑฑ์ ํ์ง ์์ง๋ง ๋ด ๋ด๋ถ ๋ก๋๋งต์ ์์ต๋๋ค.
๋ถํํ๋ drf-extensions์ Etag ๊ธฐ๋ฅ์ ๋ํ ๊ธฐ๋ณธ ๊ตฌํ ๋ฐ ๋ฌธ์๋ ๋จ์ํ ์๋ชป๋์์ผ๋ฉฐ ์ํํ ๋ฒ๊ทธ๊ฐ ์์ต๋๋ค. _response_๊ฐ ๋ณ๊ฒฝ๋๋ ๊ฒ์ด ์๋๋ผ _request_๊ฐ ๋ณ๊ฒฝ๋๋ฉด Etag๋ฅผ ๋ณ๊ฒฝํฉ๋๋ค. ์๋ฒ ์ธก ์บ์ฑ์ ๋ํด ์ํ๋ ๊ฒ์ด ์ ํํ ๋ฌด์์ด๋ฉฐ Etag์ ๋ํด์๋ ์ํ์ง ์๋ ๊ฒ์ ๋๋ค.
@mbox ๊ฐ์ฅ ์ข์ ๋ฐฉ๋ฒ์ drf-extensions์์ ์ด์ ๋ํ ๋ฌธ์ ๋ฅผ ์ฌ๋ ๊ฒ์ ๋๋ค. ๋๋ ์ฌ๊ธฐ์์ DRF "ํต์ฌ" ๋ฌธ์ ๊ฐ ์ด๋ ค ์๋ค๊ณ ์๊ฐํ๋ ๊ฒฝ์ฐ์ ๋๋ค. ํ ์คํธ์ ์คํจํ๋ฉด ๋ฌธ์ ๋ฅผ ์ดํด๋ณด๋ ๋ฐ ์ข์ ์ถ๋ฐ์ ์ด ๋ ๊ฒ์ ๋๋ค.
@mbox @xordoquy
๋ฐฉ๊ธ DRF API๋ฅผ ํตํด ๋ฆฌ์์ค๋ฅผ ์กฐ์ํ๊ธฐ ์ํ ๋๊ด์ ๋์์ฑ ์ ์ด๋ฅผ ํ์ฉํ๋ drf-extensions(https://github.com/chibisov/drf-extensions/pull/171)์ PR์ ์ ์ถํ์ต๋๋ค. ๋ชจ๋ ๊ฐ์ฒด ํ๋์ ์๋งจํฑ ํด์๋ฅผ ์ฌ์ฉํ๊ณ ์์ผ๋ฉฐ ๋ฐ๋ชจ ๋ชฉ์ ์ผ๋ก ํ
์คํธ ์ฑ์ ํฌํจํ์ต๋๋ค. Python 2.7, 3.4, 3.5์์ DRF>=3.3.1 ๋ฐ django>=1.8์ ๋ํด ํ
์คํธ๋์์ต๋๋ค.
๊ฐ์ฌ
๋ฏธ๋์ ๋
์๋ฅผ ์ํ ์ฐธ๊ณ ์ฌํญ - DRF์ ํจ๊ป Django์ ์กฐ๊ฑด๋ถ ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด ์์ ํจํค์ง๋ฅผ ๋ง๋ค์์ต๋๋ค. ๋ฐ๋ผ์ ๊ด์ฌ์ด ์๋ ๊ฒฝ์ฐ:
https://github.com/jozo/django-rest-framework-condition
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๋ถํํ๋ drf-extensions์ Etag ๊ธฐ๋ฅ์ ๋ํ ๊ธฐ๋ณธ ๊ตฌํ ๋ฐ ๋ฌธ์๋ ๋จ์ํ ์๋ชป๋์์ผ๋ฉฐ ์ํํ ๋ฒ๊ทธ๊ฐ ์์ต๋๋ค. _response_๊ฐ ๋ณ๊ฒฝ๋๋ ๊ฒ์ด ์๋๋ผ _request_๊ฐ ๋ณ๊ฒฝ๋๋ฉด Etag๋ฅผ ๋ณ๊ฒฝํฉ๋๋ค. ์๋ฒ ์ธก ์บ์ฑ์ ๋ํด ์ํ๋ ๊ฒ์ด ์ ํํ ๋ฌด์์ด๋ฉฐ Etag์ ๋ํด์๋ ์ํ์ง ์๋ ๊ฒ์ ๋๋ค.