예비군 이슈로 오늘 하루는 빈약하게...
기능 구현
네비바 등급
- 작성자 닉네임 옆에 작게 등급 이미지 들어가면 좋을듯
구현방식 고민
- 모든 페이지에서 공통으로 보이는 네비게이션 바(base.html)에 등급 이미지를 띄우려면
- 내 등급을 알아야 함
- 하지만 모든 페이지를 이동할 때마다 내 글 목록 API(/api/v1/post/my/)를 호출해서
- 개수를 세는 것은 서버에 엄청난 부담(트래픽)
구현방식
- 사용자가 처음 로그인하고 메인 홈페이지(home.html)에 접속했을 때
- 이미 잔디밭을 그리기 위해 내 글 개수를 가져옴
- 이때 계산된 내 등급 이미지 URL을 브라우저의 localStorage에 저장
- 모든 페이지에 공통으로 적용된 base.html에서는 서버에 API 요청을 보내는 대신
- 빠르게 localStorage에서 이미지만 꺼내서 닉네임 옆에 보여줌
등급 이미지 저장하기
localStorage.setItem('user_grade_img', currentGrade.imgUrl);
if (typeof checkLoginStatus === 'function') {
checkLoginStatus();
}
닉네임 옆에 이미지 보여주기
<li class="nav-item me-3 d-flex align-items-center">
<img id="nav-grade-img" src="" alt="grade" class="d-none me-2" style="width: 24px; height: 24px; object-fit: contain;">
<span class="text-white opacity-75 small">안녕하세요, <strong id="user-nickname" class="text-white">User</strong>님</span>
</li>
<li class="nav-item me-3">
<span class="text-white opacity-75 small">안녕하세요, <strong id="user-nickname"
class="text-white">User</strong>님</span>
</li>
——————————————————————————————————————[비교]—————————————————————————————————————————
<li class="nav-item me-3 d-flex align-items-center">
<img id="nav-grade-img" src="" alt="grade" class="d-none me-2" style="width: 24px; height: 24px; object-fit: contain;">
<span class="text-white opacity-75 small">안녕하세요, <strong id="user-nickname" class="text-white">User</strong>님</span>
</li>
function checkLoginStatus() {
const token = localStorage.getItem('access_token');
const nickname = localStorage.getItem('nickname');
const gradeImgUrl = localStorage.getItem('user_grade_img');
const guestMenu = document.getElementById('guest-menu');
const userMenu = document.getElementById('user-menu');
const nicknameElement = document.getElementById('user-nickname');
const navGradeImg = document.getElementById('nav-grade-img');
if (token) {
guestMenu.style.setProperty('display', 'none', 'important');
userMenu.style.setProperty('display', 'flex', 'important');
if(nickname && nicknameElement) {
nicknameElement.innerText = nickname;
}
if(gradeImgUrl && navGradeImg) {
navGradeImg.src = gradeImgUrl;
navGradeImg.classList.remove('d-none');
}
} else {
guestMenu.style.setProperty('display', 'flex', 'important');
userMenu.style.setProperty('display', 'none', 'important');
}
}
function handleLogout() {
if(confirm("정말 로그아웃 하시겠습니까?")) {
localStorage.removeItem('access_token');
localStorage.removeItem('refresh_token');
localStorage.removeItem('nickname');
localStorage.removeItem('user_grade_img');
alert("로그아웃 되었습니다.");
window.location.href = "/";
}
}
1차 완료


포스트 닉네임 등급
프론트
<div class="text-muted small">
by <span id="post-author" class="text-success fw-bold"></span> |
<span id="post-date"></span>
<span id="post-visibility-badge" class="ms-2"></span>
</div>
——————————————————————————————————————[비교]—————————————————————————————————————————
<div class="text-muted small d-flex align-items-center"> by
<img id="post-author-grade" src="" alt="grade" class="d-none ms-1 me-1" style="width: 20px; height: 20px; object-fit: contain;">
<span id="post-author" class="text-success fw-bold"></span> |
<span id="post-date" class="ms-1"></span>
<span id="post-visibility-badge" class="ms-2"></span>
</div>
백엔드
from rest_framework import serializers
from apps.post.models import Post
GRADE_SETTINGS = [
...
]
class PostDetailSerializer(serializers.ModelSerializer):
...
author_grade_image = serializers.SerializerMethodField()
...
class Meta:
model = Post
fields = [
...
"author_grade_image",
...
]
def get_author_grade_image(self, obj):
total_count = Post.objects.filter(user=obj.user, deleted_at__isnull=True).count()
for grade in GRADE_SETTINGS:
if total_count >= grade["min"]:
return grade["imgUrl"]
return GRADE_SETTINGS[-1]["imgUrl"]
def get_is_liked(self, obj) -> bool:
request = self.context.get("request")
if request and request.user.is_authenticated:
return obj.likes.filter(user=request.user).exists()
return False

작성글 조회에서 작성자의 닉네임 옆에 등급이 나오도록 추가
