오늘은 decorator에 대하여 알아보겠습니다. 🙂
함수를 받아 명령을 추가한 뒤 이를 다시 함수의 형태로 반환하는 함수입니다.
함수의 내부를 수정하지 않고 기능에 변화를 주고 싶을 때
반복을 줄이고 메소드나 함수의 책임을 확장 가능하다는 점!!
데코레이터의 구조를 먼저 살펴보죠.🤔
아래와 같습니다.
def out_func(func):
def inner_func(*args, **kwargs):
return func(*args, **kwargs)
return inner_func
example )
def decorator(func):
def wrapper(*args, **kwargs):
print('출력 1')
print(func(*args, **kwargs))
print('출력 3')
return wrapper
@decorator
def example():
return '출력 2'
# 출력 순서
example()
출력 1
출력 2
출력 3
JavaScript를 이용해 유저가 웹사이트에 로그인 한 후에 발생하는 이벤트(댓글, 게시판 글쓰기 등), 여러가지 서비스를 이용하기 위한 권한을 가진 유저인지 확인하기 위해서 많이 쓰입니다.
사용자가 로그인을 한후에 jwt를 통해 token을 발급하는데 토근을 활용하는 이유는 http통신의 stateless때문
!!
웹사이트에서 댓글, 게시판, 글쓰기 등등 서비스를 이용할때 로그인된 유저인지, 이용가능한 유저인지 확인하는 과정이 필요하기 때문입니다!!
로그인을 하게되면, 프론트엔드에게 해당되는 access_token을 전달하게 됩니다.
토큰 발행시, 토큰을 byte형식이 아닌 str형식으로 해야 하는데 그 이유는 http통신으로 전달할때 byte형식은 전달이 안되기 때문!!
서비스를 이용할 때, 권한을 확인하기 위하여 프론트엔드에서 HTTP 헤더를 통해 토큰을 전달 받는다.
jwt토큰은 byte타입이므로 jwt토큰을 str타입으로 decode한다.
access토큰을 발행했을 때 아래와 같이 만들었는데,
access_token = jwt.encode({'id' : 1}, SECRET, algorithm = 'HS256')
이때 첫 부분, 즉 {'id' : 1}
정보를 바탕으로 database의 id와 access_token의 정보를 비교하여 준다.
4. 토큰이 일치할 경우, request할 객체에 프론트엔드에게 전달한다.
def login_deco(func):
def wrapper(self, request, *args, **kwargs):
try:
access_token = request.headers.get('Authorization', None)
payload = jwt.decode(access_token, SECRET_KEY, algorithm='HS256')
account = Account.objects.get(name= payload['name'])
request.account = account
except jwt.exceptions.DecodeError:
return JsonResponse({'message' : 'INVALID_TOKEN' }, status=400)
except Account.DoesNotExist:
return JsonResponse({'message' : 'INVALID_USER'}, status=400)
return func(self, request, *args, **kwargs)
return wrapper
이미 로그인이 된 상태에서도 어떠한 서비스에 접근 할때에는 권한이 필요하다.
따라서 내가 구현했던 인스타그램에서는 posting과 comment부분에 필요하다!
@login_deco
참고!!
class PostingView(View):
@login_deco
def post(self, request):
try:
data = json.loads(request.body)
user = data['user']
content = data['content']
img_url = data['img_url']
get_user = Account.objects.get(name = user)
Posting(
user = get_user,
content = content,
img_url = img_url,
).save()
return JsonResponse({'message': 'SUCCESS22'}, status = 200)
except KeyError:
return JsonResponse({'message': 'KEY_ERROR'}, status = 400)
# DoesNotExist는 get에서 조건에 맞는 data가 없을 경우 발생됨. filter의 경우 [] return
except Account.DoesNotExist:
return JsonResponse({'message': 'Account_DoesNotExist'}, status = 401)
except json.decoder.JSONDecodeError:
return JsonResponse({'message': 'JSON_TYPE_Error'}, status = 401)
except ValueError:
return JsonResponse({"message": "VALUSE_ERROR"}, status = 400)
@login_deco
def get(self, request):
posted_data = Posting.objects.values()
# print(list(posted_data))
return JsonResponse({'message': list(posted_data)}, status = 200)
class CommentView(View):
@login_deco
def post(self, request):
try:
data = json.loads(request.body)
comment_user = data['user']
comment_content = data['content']
post_comment_id = data['post'] # post_id는 database에서 post의 id와 동일하게
user_name = Account.objects.get(name = comment_user)
post_id = Posting.objects.get(id = post_comment_id)
except KeyError:
return JsonResponse({'message': 'KEY_ERROR'}, status = 400)
except Account.DoesNotExist:
return JsonResponse( {'message': 'Account_DoesNotExist'}, status = 401)
except Posting.DoesNotExist:
return JsonResponse( {'message': 'Post_DoesNotExist'}, status = 401)
except json.decoder.JSONDecodeError:
return JsonResponse({'message': 'JSON_TYPE_Error'}, status = 401)
except ValueError:
return JsonResponse({"message": "VALUSE_ERROR"}, status = 400)
Comment(
user = user_name,
post = post_id,
content = comment_content
).save()
return JsonResponse({'message':'COMMENT_SUCCESS'}, status=200)
@login_deco
def get(self, request):
try:
if(Comment.objects.filter(post_id = "1").exists()):
selected_data = Comment.objects.filter(post_id = "1").values()
print(selected_data)
if not selected_data:
return JsonResponse({'message': 'NO_COMMENT'})
return JsonResponse({'message': list(selected_data)}, status = 200)
else:
return JsonResponse({'message': 'POST_NOT_EXIST'}, status = 401)
except Comment.DoesNotExist:
return JsonResponse( {'message': 'Comment_NOT_EXIST'}, status = 401)