기술블로그-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 객체 사용이 필수입니다!