반응형

좋아요 기능은 단순히 게시글의 좋아요 수를 1 증가시키는 기능이다.
하지만 여러 사용자가 동시에 좋아요를 누를 수 있기 때문에 단순히 Python 코드에서 `+= 1`을 사용하는 방식은 주의가 필요하다.
좋아요 View 구현
def post_like_view(request, post_id):
post = get_object_or_404(Post, id=post_id)
post.points = F("points") + 1 # post.points = F()
post.save()
post.refresh_from_db()
return render(
request, template_name="post_detail.html", context={"post": post}
)
get_object_or_404()
` post = get_object_or_404(Post, id=post_id)`
- 데이터가 존재하지 않으면 DoesNotExist 예외를 직접 처리하지 않고, 자동으로 404 응답 반환
F Expression
`F()`: Django에서 제공하는 표현식
- Python에서 값을 계산하는 것이 아니라 데이터베이스에서 직접 값을 계산하도록 SQL을 만들어줌
post.points = F("points") + 1
post.save()
# 위 코드는 아래와 유사하게 동작
UPDATE post
SET points = points + 1
WHERE id = 1;
경쟁 상태(Race Condition)
- 두 개 이상의 프로세스나 스레드가 공유 자원(데이터, 파일 등)에 접근하여 이를 읽거나 쓰는 과정에서 실행 순서에 따라 예상치 못한 결과가 발생하는 상황
만약, 사용자 A와 사용자 B가 동시에 좋아요를 누를 경우, 둘 다 동일한 값을 읽어 +1을 했기 때문에 계산이 누락될 수 있다.
`F()`를 사용하면 Python에서 값을 읽고 계산하는 것이 아니라, 데이터베이스가 직접 현재 값을 기준으로 증가시키므로 동시에 요청이 들어와도 안전하다.
refresh_from_db()
`F()`를 사용해 저장한 직후에는 Python 객체의 post.points 값이 실제 숫자가 아니라 F("points") + 1 표현식 상태로 남아 있을 수 있다.
따라서 변경된 값을 다시 확인하거나 템플릿에 최신 값을 넘기려면 데이터베이스에서 값을 다시 가져와야 하는데 `refresh_from_db()`를 사용한다.
이 코드를 실행하면 DB에 저장된 최신 값으로 post 객체가 갱신된다.
[참고] 실전! Django 입문 강의
반응형