기술블로그-Django편

🔄 Django에서 access_count += 1 vs F("access_count") + 1 완전 비교

Chansman 2025. 5. 14. 13:26

🔄 Django에서 access_count += 1 vs F("access_count") + 1 완전 비교


✅ 개요

Django에서 숫자 필드를 1 증가시킬 때 두 가지 방식이 있습니다:

  • 일반 방식: access_count += 1
  • F 객체 방식: access_count = F("access_count") + 1

언뜻 보면 비슷하지만, 데이터베이스 처리 방식과 동시성 안정성에서 큰 차이가 있습니다.


1️⃣ 일반 방식: += 1

short_url = ShortURL.objects.get(id=1)
short_url.access_count += 1
short_url.save()

⚙️ 동작 흐름

1. DB에서 현재 값 조회 → access_count = 10
2. Python에서 1 더함 → access_count = 11
3. save() → DB에 11 저장

❌ 문제점: Race Condition 발생

두 명의 사용자가 동시에 접근할 경우:

사용자 A: access_count = 10 → 11
사용자 B: access_count = 10 → 11 (같은 값!)
→ 최종 DB 값: 11 (접근은 2번인데 1만 증가)

2️⃣ F 객체 방식: F("access_count") + 1

from django.db.models import F

short_url.access_count = F("access_count") + 1
short_url.save()

⚙️ 동작 흐름

1. F 객체로 연산 명령 지정
2. save() 실행 시 다음 SQL 수행:

   UPDATE shortener_shorturl
   SET access_count = access_count + 1
   WHERE id = 1;

✅ 이 쿼리는 DB에서 직접 연산하기 때문에 동시 요청에도 정확히 처리됩니다.

예:

  • A 요청 → +1 → 11
  • B 요청 → +1 → 12 (정확히 반영)

📊 비교 정리표

항목 += 1 방식 F() + 1 방식

연산 위치 Python 메모리 DB 내부 (SQL)
동시성 문제 ❌ 있음 (Race 발생) ✅ 없음 (DB가 직접 연산)
사용 대상 간단한 환경 실제 서비스, 트래픽 多

🧠 실전 팁

  • ✅ 데이터 증가, 조회 수, 좋아요 수처럼 여러 사용자가 동시에 갱신할 가능성이 있는 경우 → 무조건 F() 객체 사용하세요.
  • ❌ 단순 += 1은 장고가 DB에서 가져온 값을 메모리에 보관했다가 다시 저장하기 때문에, 최근 값과 충돌할 수 있음

🔁 시각적 흐름도

[ 사용자 요청 1 ]      [ 사용자 요청 2 ]
     ↓                     ↓
access_count = 10      access_count = 10
+1 → 11               +1 → 11
     ↓                     ↓
save() → DB 저장       save() → 덮어쓰기
⇒ 최종: 11 (❌ 오류)
[ 사용자 요청 1 ]      [ 사용자 요청 2 ]
     ↓                     ↓
access_count = F(...)   access_count = F(...)
save() → +1             save() → +1
⇒ DB가 직접 계산 → 정확히 2 증가 (✅)

✅ 결론

F 객체는 단순한 편의 기능이 아니라, 실제 서비스를 안정적으로 운영하기 위한 동시성-safe 기능입니다.

👍 조회 수, 클릭 수, 좋아요 수 같이 "증가"가 빈번한 상황에서는 F 객체 사용이 필수입니다!