본문 바로가기

전체 글150

웹소켓 요청을 인터셉터에서 처리하기(feat filter) 개요웹소켓을 처음 도입했을 때, 어차피 그냥 요청이니까 filter에서 인증 처리하면 되지 않을까? 생각했다.처음엔 잘 되네 싶었는데, 시간이 지나면서 왜 이 구조가 잘못됐는지 깨달은 점을 기록하려 한다 WebSocket웹소켓은 흔히 말하는 HTTP 요청/응답 기반 구조랑은 다르다.한번 연결되면 계속 연결 상태가 유지되는 연결 지향형(Connection-Oriented) 프로토콜이다.웹소켓이 처음 연결될 때는 HTTP 프로토콜로 요청이 보내지지만,Upgrade: websocket이라는 헤더를 통해 프로토콜을 바꾸는 핸드쉐이크 과정을 거친다.이 핸드쉐이크 과정에서 서버가 승인하면 비로소 TCP연결이 완성된다.따라서 정리하자면1. HTTP 요청 (/ws?token=xxx) -> 핸드쉐이크 시작2. 서버가 .. 2025. 4. 22.
DDD스럽게 user엔티티 사용하기 개요DDD를 공부하면서 가장 고민되는 부분 중 하나가 user같은 기본적인 엔티티를 어떻게 잘 설계할까.. 하는거다그냥 단순히 데이터만 담는 엔티티가 아니라 도메인 모델로서의 역할을 어떻게 제대로 할 수 있을까 하는 생각?오늘은 프로젝트의 user도메인을 보면서, DDD스럽게 설계된 엔티티는 어떤 느낌인지 살펴보자 VO 적절히 활용하기@Entity@Table(name = """user""")class User( @Embedded var information: UserInformation, @AttributeOverride(name = "value", column = Column(name = "password", nullable = false)) @Embedded var pas.. 2025. 4. 21.
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.
코프링스러운 코드 작성법 https://github.com/woowacourse/service-apply GitHub - woowacourse/service-apply: 우아한테크코스 지원부터 최종 합격까지 모든 과정을 관리한다.우아한테크코스 지원부터 최종 합격까지 모든 과정을 관리한다. Contribute to woowacourse/service-apply development by creating an account on GitHub.github.com이 코드를 보면서 코틀린스러움에 익숙해지고 있다.. 수많은 멀티모듈, msa 속에서 찾아낸 모놀리ㅜㅜ크롤링을 코틀린으로 해본 경험이 있긴 한데 함수형 프로그래밍 흉내만 낸 셈이라 코프링에 완전 익숙해지지 않은 거 같다게시판 하나 제대로 만들고, 코루틴을 한번 사용해보는 게 이 .. 2025. 4. 15.
11. Real MySQL 4장 InnoDB InnoDB 버퍼 풀(Buffer Pool)InnoDB 버퍼 풀: 자주 접근하는 데이터와,인덱스 페이지를 메모리에 캐싱해서 디스크 I/O를 최소화하는 메모리 기반 캐시데이터를 메모리에 저장함으로써 읽기/쓰기 작업을 디스크가 아닌 버퍼 풀에서 처리하여 쿼리 성능을 크게 향상시킴 설정: innodb_buffer_pool_size값이 너무 작으면: 빈번한 디스크 I/O로 성능 저하값이 너무 크면: OS 및 기타 프로세스의 메모리 부족으로 스왑이나 시스템 충돌 발생 가능동적 조절: Mysql 5.7 이상에서는 서버 재시작 없이 'SET GLOBAL innodb_buffer_pool_size = 값' 으로 크기를 동적으로 변경 가능인스턴스 분할: 높은 동시성 환경에서는 버퍼 풀을 여러 인스턴스로 나누어 경합을 줄.. 2025. 4. 13.
알림 구현(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.
10. Real MySQL 4장 아키텍처 Mysql 아키텍처Mysql 서버 구조:쿼리 파싱, 최적화, 실행을 담당하는 Mysql 엔진과실제 데이터를 디스크에 저장하고, 조회하는 스토리지 엔진으로 나눔. Mysql 엔진은 커넥션 핸들러, SQL 파서, 전처리기, 옵티마이저 등으로 이루어짐 스토리지 엔진은 대표적으로 InnoDB: 트랜잭션, 외래 키, 버퍼 풀 등을 지원MyISAM: 빠른 읽기, 단순한 구조, 트랜잭션 없음SHOW ENGINES; 하면 스토리지 엔진 확인 가능함 스레딩 모델Foreground 스레드:클라이언트 요청을 처리(커넥션 연결 담당)하고, 쿼리 처리 후 스레드 캐시에 반환되어 재사용됨이미 스레드 캐시에 일정 개수 이상의 대기 중인 스레드가 있으면, 스레드를 종료시켜서 일정 개수의 스레드만 캐시에 존재하게 함데이터를 Mysql.. 2025. 4. 11.
알림 구현(2) 웹소켓 세션 다중 클라이언트, 다중 인스턴스 환경 개요실시간 알림에 사용되는 웹 소켓 세션이 현재는 다중 클라이언트와, 다중 인스턴스 환경에서 취약점을 보이고있다.1. pc로 접속한 뒤 모바일로 접속하면 pc환경에서의 세션은 끊기고,2. 중앙화된 세션 관리 저장소가 없어서 요청마다 세션 상태가 다르다. 오늘은 이 두개를 보완해보장  다중 클라이언트 허용현재 세션은 이렇게 HashMap 형태로 딱 하나만 들어가게끔 설계되어있는데, 자료구조를 좀 바꿔서한 Id에 대해 여러 웹소켓세션을 저장하도록 하면 된다.이렇게 thread safe한 불변 리스트를 사용하도록 바꿔주고websocket king client에서 두 개의 클라이언트를 켜놓고 실험해보면,같은 알림을 동시에 받는 걸 확인할 수 있다~!  다중 인스턴스 환경현재 websocket세션은 각 인스턴스의.. 2025. 4. 11.
조회 성능 향상시키기(7) Semaphore에서 Mutex로 갈아타기 개요현재 단일 인스턴스 환경에서 비동기 쿼리 동시실행 제어를 Semaphore로 진행하고 있었다.근데 생각해보니까 하나만 허용할거면 Mutex가 더 나을 거 같아서 리팩토링 하게 되었다  Mutex vs Semaphore항목MutexSemaphore주 목적상호 배제 (Mutual Exclusion)리소스 수 제한된 접근 제어값0 또는 1 (이진락)0 이상 (카운터)오버헤드보통 더 적음보통 더 큼시스템 콜대부분 커널 공간 필요대부분 커널 공간 필요사용자 수1개 스레드만 소유 가능여러 스레드가 접근 가능 뮤텍스가 보통 더 가벼운데, 오직 하나의 스레드만 접근 허용하기 때문에 0 또는 1의 간단한 상태만 관리하면 되기 때문이다.커널 락 사용 방식이나 구현체에 따라 차이는 있지만, 카운트 관리가 필요 없는 뮤텍.. 2025. 4. 10.