TIL

[2024.05.02] Today I Learned(Serializer, AWS CloudFront, commit message)

싯타마 2024. 5. 2. 23:28

오늘 배운 것

1. Django REST Framework(이하 DRF) Serializer 옵션값

2. commit message의 중요성

3. AWS CloudFront

 

1. DRF 옵션값

오늘은 나에게 긴급 이슈 요청이 들어와서 서둘러 일을 처리해야 했다. 전에 작성했던 코드를 수정했어야 했는데 오랜만에 보다 보니 기억이 잘 나지 않았고, 추가로 아직 까지도 Django Restfamework가 익숙하지 않아서 수정하는데 헤매었다 그러던 중 선임님이 이슈를 같이 해결해 주셨고...! 결국 무임승차를 하게 되었다.... 크으 나는 제한된 시간 안에 코드를 짤 때는 빨리해야 된다는 압박감에 머리솟이 하에 지는 것 만 같은데 선임 분이 해주셔서(?) 무사히 끝낼 수 있었다. (정말 멋져....)

 

결론적으로 내가 못 찾았던 원인은 

Django REST Framework의 Serializer 클래스의 옵션값이 설정되어 있었다.

Serailizer에서는 클래스의 필드에 옵션값을 설정해서 세밀한 제어를 가능하게 해 준다.

그러면 짧게 옵션값들에 대해 알아보자.

 

1. read_only

- True이면 필드는 직렬화할 때만 사용되고 역직렬화는 허용되지 않는다. (API를 읽을 수는 있지만 수정할 수는 없다.

from rest_framework import serializers

class UserSerializer(serializers.Serializer):
	user_id = serializers.IntegerField(read_only=True)

 

2. write_only 옵션 

- True이면 이 필드는 역직렬화할 때만 사용되고 직렬화는 허용하지 않는다. (데이터를 입력받을 때는 사용되지만 출력할 때는 보이지 않는다. ex) 비밀번호 )

from rest_framework import serializers

class UserSerializer(serializers.Serializer):
	password = serializers.CharField(write_only=True, style={'input_type': 'password'})

 

3. required

- True이면 필드가 반드시 제공되어야 한다. (기본값은 True)

 

4. default

- 필드값이 제공되지 않을 때 사용할 기본값을 설정한다.

from rest_framework import serializers

class UserSerializer(serializers.Serializer):
	email = serializers.EmailField(required=True, default="no-reply@example.com")

 

 - required True라서 email은 필수값이고 없을 땐 default값으로 설정한다.

 

5. allow_null

- True이면 필드값으로 'null'을 허용한다. (기본값은 False)

from rest_framework import serializers

class UserSerializer(serializers.Serializer):
    bio = serializers.CharField(allow_null=True, required=False, help_text="Short biography of the user")

 

6. validators

- 필드에 적용할 추가적인 검증 함수 목록이다. 이를 통해 사용자 정의 검증 로직을 적용할 수 있다.

from rest_framework import serializers

class UserSerializer(serializers.Serializer):
	age = serializers.IntegerField(validators=[lambda value: value >= 18])

 

7. error_messages

- 필드 유효성 검증 실패 시 표시할 에러 메시지를 사전 형식으로 정의한다.

from rest_framework import serializers

class UserSerializer(serializers.Serializer):
	username = serializers.CharField(error_messages={'blank': 'Username cannot be empty.'})

 

8. label

- 필드의 레이블을 지정한다. HTML 폼에서 필드의 설명으로 사용된다.

 

9. help_text

- 필드 사용에 대한 추가적인 도움말을 제공한다. HTML 폼에서 사용된다.

 from rest_framework import serializers

class UserSerializer(serializers.Serializer):
 	first_name = serializers.CharField(label="First Name", help_text="Enter your first name")

 

위 옵션값들을 extra_kwargs를 통해 한꺼번에 지정하는 방법도 있다.

from rest_framework import serializers


EXTRA_KWARGS = {
    'user_id': {'read_only': True},
    'password': {
        'write_only': True,
        'style': {'input_type': 'password'},
        'help_text': 'Your password must be 8-20 characters long.'
    },
    'email': {
        'required': True,
        'default': 'no-reply@example.com',
        'validators': [lambda value: value.endswith('@example.com')],
        'error_messages': {'invalid': 'This email is not valid.'}
    },
    'first_name': {
        'label': 'First Name',
        'help_text': 'Enter your first name.'
    },
    'last_name': {
        'write_only': True,
        'style': {'template': 'custom_input.html'}
    },
    'bio': {
        'allow_null': True,
        'required': False
    }
}

class UserSerializer(serializers.Serializer):
    user_id = serializers.IntegerField()
    username = serializers.CharField()
    email = serializers.EmailField()
    password = serializers.CharField()
    first_name = serializers.CharField()
    last_name = serializers.CharField()
    bio = serializers.CharField()
    
	extra_kwargs = SALE_EXTRA_KWARGS

 

2. commit message의 중요성

선임님의 도움을 주던 중 내가 짠 과거 코드에 대해서 물어봤다... 그래서 github의 커밋메시지를 보았는데... 대충

'정확한 oo데이터 수집을 위한 수정, XX 기능 추가'

이런 느낌의 메시지였는데 내가 보아도 엉망인 커밋이었다.

 

한 번에 두 가지 이슈를 커밋해 버려서

내가 짠 코드가 전자에 관한 내요인지 후자에 관한 내용인지 구분을 해야 할 수밖에 없었다....

 

코드를 짜는 것도 중요하지만 이런 커밋메시지를 정리를 잘하거나 지라 이슈관리를 잘해야 함을 느꼈다. 

참고로 선임님은 개발 실력도 좋으신데... 정리도 초깔끔하게 핵심내용만 작성을 한다는 것이다...(여러모로 배울 점이 많은 분...)

 

반성을 하게 됐다. 실력이 없으면 정리라도 깔끔하게 잘해야 하는데... 아니 정리를 잘하는 것도 실력인가..! 허허

최대한 커밋메시지라도 잘 쓰려고 노력을 해봐야겠다.

커밋메시지 관련해서는 선임님이 추천해 주신 블로그글을 보고 괜찮다고 느껴졌다.... 남의 글을 함부로 링크를 걸면 안 될 것 같아서..

구글에 '커밋메시지 작성 가이드'를 검색하면 좋은 글이 많이 있다. 앞으로 참고하면서 신경 써서 작성을 해봐야겠다.

 

 

3. AWS CloudFront

오늘 겪은 이슈 중에는 이미지 업로드가 되었음에도 업로드된 이미지로 바뀌지 않고 이전 이미지를 출력하는 현상도 있었다. 

이 문제도 혼자 했으면.... 몰랐겠지만.... 옆에서 듣고 계시던 CTO님이 해결을 해주셨다...! (도움만 받는 인생..ㅋ 성장해서 은혜를 갚아주마)

 

이 문제는 AWS의 CloudFront와 관련이 있었다.

https://docs.aws.amazon.com/ko_kr/AmazonCloudFront/latest/DeveloperGuide/Introduction.html

 

Amazon CloudFront란 무엇입니까? - Amazon CloudFront

Amazon CloudFront란 무엇입니까? Amazon CloudFront는 .html, .css, .js 및 이미지 파일과 같은 정적 및 동적 웹 콘텐츠를 사용자에게 더 빨리 배포하도록 지원하는 웹 서비스입니다. CloudFront는 엣지 로케이션

docs.aws.amazon.com

아마존 홈페이지에서 가이드 내용이다.

Amazon CloudFront는. html,. css,. js 및 이미지 파일과 같은 정적 및 동적 웹 콘텐츠를 사용자에게 더 빨리 배포하도록 지원하는 웹 서비스입니다. CloudFront는 엣지 로케이션이라고 하는 데이터 센터의 전 세계 네트워크를 통해 콘텐츠를 제공합니다.

 

AWS의 콘텐츠 전송 네트워크(CDN) 서비스라고도 하는데 전 세계에  에지로케이션(Edge Server(Locatcion))을 두고 Client와 가장 가까운 Edge Server를 찾아서 그곳에 캐싱해 두었던 데이터를 가져와서 제공하는 시스템이다. (캐시 되어있고 가까운 서버를 찾아서 가져오므로 속도 up)

 

Edge Location ? 

- CloudFront 서비스가 콘텐츠를 캐싱하고 Client에게 제공하는 지점 혹은 캐시 서버를 의미한다.  전 세계 주요 도시에 300개 이상의 서버가 분포되어 있다. 

- 사용자가 CloudFront를 통해 서비스하는 콘텐츠를 사용자가 요청하면 지연 시간이 가장 낮은 에지 로케이션으로 라우팅 됨으로 콘텐츠 전송 성능이 뛰어나다.

 

하지만 내가 겪은 이슈는 요런 장점과는 별개로 CloudFront를 사용할 때 이미지 업데이트 후 최신화된 이미지를 보여줘야 하는데 캐시 된 데이터를 보여주게 되는 문제였다.

 

이를 해결하기 위해서 여러 방법이 있다.

 

1. 캐시데이터 무효화

- 요청전송: CloudFront배포에 대한 캐시 무효화 요청하여 Edge Location에 저장되었던 캐시데이터를 삭제한다. 이 과정은 전 세계의 여러 Edge Location에 적용돼야 할 수도 있어서 시간이 좀 걸릴 수 있다. 하지만 최신 버전의 콘텐츠로 바뀌고 나면 다시 캐시데이터를 사용하게 되므로 그 후에 로딩할 때는 이미지가 빠르게 처리된다.

 

2. 캐시 만료 설정변경

- CloudFront의 배포설정에 캐시 만료시간(TTL, Time To Live)을 줄이는 방법도 있다. 이는 캐시 된 파일이 더 빨리 만료가 되어 자주 업데이트가 필요한 콘텐츠의 경우 유리 할 수 있다.

 

3. 콘텐츠 버전관리 

네, 맞습니다. 당신이 겪은 이슈는 CloudFront를 사용할 때 매우 흔히 발생하는 문제로, 캐시된 오래된 콘텐츠가 새로 업데이트된 콘텐츠 대신에 계속해서 제공되는 것입니다. 이런 현상은 캐시된 데이터가 아직 유효하다고 판단되어 CloudFront가 오리진 서버에서 새로운 데이터를 가져오지 않기 때문에 발생합니다.

4. Tag와 Last-Modified 헤더 사용
   - 오리진 서버에서 콘텐츠에 `ETag` 또는 `Last-Modified` 헤더를 설정하여 변경 사항을 관리할 수 있습니다. CloudFront는 이 헤더를 기반으로 콘텐츠가 변경되었는지를 판단하고, 필요에 따라 새로운 콘텐츠를 가져옵니다.

 

우리는 CloudFont를 사용하는 이미지가 자주 바꾸지 않는다는 가정으로 이미지를 교체할 때 캐시데이터 무효화 요청을 같이 보내주는 걸로 결정했다. 

 

그리고 추가로 리전(Region)에 대해서도 배웠다.

 

리전(Region)?

- 특정 지리적 위치에 위치한 물리적 데이터 센터 그롭을 의미한다. 각 리전은 가용영역(Avaliability Zones)으로 구성되며 리전 구조는 높은 가용성과 장애 내성을 제공한다.

 

즉 CloudFront 또한 물리적 데이터 센터를 나누어서 분포시켰으므로 리전구조라고 할 수 있다.

 

가용 영역(Availability Zone, AZ)?

- 하나의 리전 내에 위치한 여러 개의 물리적 데이터 센터를 의미합니다.

각 가용 영역은 일반적으로 지리적으로 가까운 위치에 있지만, 다른 가용 영역과는 독립적으로 운영됩니다. 이들은 서로 다른 전력, 냉각 및 네트워킹 인프라를 사용하여, 하나의 가용 영역에 문제가 발생해도 다른 가용 영역의 리소스가 영향을 받지 않도록 설계되어 있습니다.

 

 

느낀 점

오늘 하루도 내가 많이 부족하다고 느껴졌다. 개발 속도도 느리고 아직 모르는 개념들이 너무 많았다. 개발자를 계속할 수 있을까 라는 의심이 들지만... 아직은 좀 더 노력해보고 싶다! 그리고 하루에 꼭 TIL을 해야 되겠다고 마음먹고 한 달 만에 쓰는 TIL이다..ㅋㅋ 반성하자 제발 열심히 좀 살자~

'TIL' 카테고리의 다른 글

[2024.03.25] 오늘의 TIL  (1) 2024.03.26