개인 공부용/ㅇㅅㅇ8 Django mysql - 게시판 조회수 DB기반 동시성 제어 개요인턴으로 일하게 된 회사에서 django를 주로 사용해서 crud게시판을 가볍게 만들어보고있다.사실 떨어진 줄 알고 kotlin이랑 dart로 모바일 앱 출시까지 할 계획으로 만들고 있었는데 붙을 줄 알았으면 백엔드를 python으로 할걸 그랬다 ㅋㅋdjango를 가볍게나마 해본 결과 이 미친 언어는 생산성이 말도안된다 그만큼 규모가 커지면 관리가 힘들려나? 힘들겠지..의도치 않게 언어를 C -> java -> kotlin -> python 순으로 접하면서 점점 인간의 언어에 가까워지고 있는데 한 단계 올라갈 때 마다 이게 왜 되냐? 하게되는 거 같다어쨋든 조회수를 django에서 컨트롤해보자 동시성 제어를 제대로 해본 적은 없지만 그동안 이론 공부 했던 걸 잘 생각하면서,, 조회수 증가 로직에서의.. 2025. 5. 3. 웹소켓 요청을 인터셉터에서 처리하기(feat filter) 개요웹소켓을 처음 도입했을 때, 어차피 그냥 요청이니까 filter에서 인증 처리하면 되지 않을까? 생각했다.처음엔 잘 되네 싶었는데, 시간이 지나면서 왜 이 구조가 잘못됐는지 깨달은 점을 기록하려 한다 WebSocket웹소켓은 흔히 말하는 HTTP 요청/응답 기반 구조랑은 다르다.한번 연결되면 계속 연결 상태가 유지되는 연결 지향형(Connection-Oriented) 프로토콜이다.웹소켓이 처음 연결될 때는 HTTP 프로토콜로 요청이 보내지지만,Upgrade: websocket이라는 헤더를 통해 프로토콜을 바꾸는 핸드쉐이크 과정을 거친다.이 핸드쉐이크 과정에서 서버가 승인하면 비로소 TCP연결이 완성된다.따라서 정리하자면1. HTTP 요청 (/ws?token=xxx) -> 핸드쉐이크 시작2. 서버가 .. 2025. 4. 22. Spring Security에서 JWT를 Stateless하게 사용하기 개요Spring security와 jwt를 함께 사용할 때 항상 고민되는 주제가 '정말 무상태하게 구성하고 있는걸까' 인 거 같다.단순히 토큰을 발급하고 필터에서 인증하는 걸로 끝나면 안되고, 좀 신경써야 할 부분이 있다고 생각한다. 우선 stateless하다는 건 서버가 클라이언트의 상태를 기억하지 않는다는 것이다.로그인한 사용자의 정보를 세션에 담아두지 않고, 매 요청마다 인증 정보가 포함되어야 한다.결국 이 구조를 위해 JWT를 사용하는거고.. 토큰 자체가 인증 정보를 담고 있어야 한다. 그런데 여기서 중요한 건, JWT를 단순히 사용한다 해서 자동으로 stateless해지는 게 아니라는 점이다.예를 들어, 토큰 검증 후 유저 정보를 DB에서 조회해서 세션이나 컨텍스트에 올려버리면 그건 이미 상태를.. 2025. 4. 20. MESI 프로토콜 MESI 프로토콜MESI 프로토콜은 멀티코어 CPU 환경에서 캐시 일관성(Coherency)을 유지하기 위한 프로토콜이다.MESI는 각각의 캐시 라인이 4가지 상태 중 하나를 가지도록 해서, 각 CPU 코어가 동일한 메모리에 주소에 접근하더라도 데이터 불일치를 막아주는 방식이다. MESI의 4가지 상태는 다음과 같다:Modified (수정)이 캐시 라인만 최신 데이터를 가지고 있고, 메모리에는 반영 안 됨다른 캐시에 없음 + dirty 상태Exclusive (배타적)이 캐시 라인만 데이터 가지고 있고, 메모리와 동일다른 캐시에 없음 + clean 상태Shared (공유)여러 캐시가 동일한 데이터를 가지고 있음 + 메모리와 동일다른 캐시에도 있음 + clean 상태Invalid (무효화)더 이상 유효하지 .. 2025. 4. 18. 알림 구현(3) 확장성을 고려한 리팩토링: 전략패턴 개요현재 알림 시스템은 딱 한 유형, '댓글이 달렸을 때' 만을 기준으로 개발되어있다.@Slf4j@Aspect@Component@RequiredArgsConstructorpublic class NotificationProducer { private final KafkaTemplate kafkaTemplate; private final PostRepository postRepository; @Around("@annotation(triggerNotification)") public Object notify(ProceedingJoinPoint joinPoint, TriggerNotification triggerNotification) throws Throwable { Obje.. 2025. 4. 12. 알림 구현(2) 웹소켓 세션 다중 클라이언트, 다중 인스턴스 환경 개요실시간 알림에 사용되는 웹 소켓 세션이 현재는 다중 클라이언트와, 다중 인스턴스 환경에서 취약점을 보이고있다.1. pc로 접속한 뒤 모바일로 접속하면 pc환경에서의 세션은 끊기고,2. 중앙화된 세션 관리 저장소가 없어서 요청마다 세션 상태가 다르다. 오늘은 이 두개를 보완해보장 다중 클라이언트 허용현재 세션은 이렇게 HashMap 형태로 딱 하나만 들어가게끔 설계되어있는데, 자료구조를 좀 바꿔서한 Id에 대해 여러 웹소켓세션을 저장하도록 하면 된다.이렇게 thread safe한 불변 리스트를 사용하도록 바꿔주고websocket king client에서 두 개의 클라이언트를 켜놓고 실험해보면,같은 알림을 동시에 받는 걸 확인할 수 있다~! 다중 인스턴스 환경현재 websocket세션은 각 인스턴스의.. 2025. 4. 11. 알림 구현(1) Kafka + Redis Pub/Sub + WebSocket MVP 개요이번 프로젝트에서 나는 "알림 기능" 파트를 맡게 되었다. 프로젝트 주제는 실시간 게임 매칭 + 게임 공략글 공유 웹서비스이며, 알림은 전반적인 UX의 핵심 기능 중 하나였다. 알림은 두 가지 방향으로 나눠서 설계하기로 했다.RDB 기반 알림: 로그인 시 확인할 수 있는 알림 목록, 읽음 처리 등 상태 저장용, 푸시 알림이 유실되면(상대 사용자가 WebSocket Session이 없으면) 이곳에 모은다.푸시 기반 알림: 실시간 반응성과 UX 중심의 알림(브라우저 푸시)우선 RDB 연동 없이 "글에 달린 댓글"의 실시간 알림 스트리밍 기능 MVP부터 구현하였다. 이 글은 그 과정을 정리한 것이다. 구성1. 모든 유저는 웹 로그인 시 WebSocketSession을 부여받는다.클라이언트에서 /ws?to.. 2025. 4. 7. JWT Token BlackList TTL을 효율적으로 설정하기 개요기존에는 BlackList의 TTL을 대강 AccessToken의 Exp기간과 똑같이 잡았었는데,유저가 만료시간 직전에 로그아웃을 하는 경우 Redis에 불필요하게 오랫동안 BlackList를 저장하게 된다. 30분짜리 AccessToken의 만료시간이 1분 남았을 때,블랙리스트로 30분간 저장해놓게 된다면 29분간 쓸모없는 데이터가 생기는 것이다. 솔직히 블랙리스트 하나 당 216B밖에 되지 않아서 무시해도 될 수준 아닌가? 싶지만, 100만건이 한번에 몰리면 216MB가 된다.거기다 우리는 RefreshToken도 Redis로 관리하므로 함께 생각하는 편이 좋다. 해결public void addToBlackList(String token) { String blackPrefix = jwtSe.. 2025. 4. 3. 이전 1 다음