기록/IT

독서 및 강의_2025

무심한고라니 2025. 3. 2. 17:09

2025년 상반기에 읽을 독서 및 강의 목록을 남겨본다. 꼭 읽어야지! 라는 마음으로 남기는 것도 있고... 읽어가면서 정리한 부분을 링크로 남기고자 한다. 사실 강의 같은 부분은 용어 등에 익숙해지고 큰 틀을 잡는 용도로 들은 것도 있어 정확치 않은 부분이 있을 수도 있다.

 

--------

  1. Do it! 자료구조와 함께 배우는 알고리즘 입문(자바편) (진행중)
    • 국비를 통해 일을 시작해 당면한 업무 처리에 급급하다보니 알고리즘 관련해서 공부한 적이 없었다(자바가 아닌 SQL로 데이터를 가져오는 경우가 많다 보니..). 그러다 보니 코딩 테스트 같은 것도 잘 보지 못했었고... 이참에 조금 책 읽고 기본적인 부분을 공부해서 Leetcode 기본 문제 정도 풀 수 있는 게 상반기 목표다.
  2. 자바로 배우는 핵심 자료구조와 알고리즘
    • 알고리즘 책 한 권으로는 좀 부족하지 않을까 해서 얇지만 좀 있어보이는 책 하나를 더 샀다. 이건 위 책 읽고 살펴보려고 한다.
  3. 테스트 주도 개발 시작하기
  4. 안드로이드 앱 프로그래밍

여기까지 새로 읽을 책 목록이라면 2024년 읽고자 했는데 못 읽는 목록도 마저 읽으려고 한다.

 

  1. 육각형 개발자
  2. .

--------

  • 동시성 프로그래밍
    1. 재고시스템으로 알아보는 동시성 이슈 해결방법(완료)
      • 일하면서 트랜잭션만 생각했지, 동시성을 고려한 코드를 짠 적이 없어서 수강했다(근데 왜 지금껏 문제가 없었는지 의문). 강의에선 Synchronized, DB Lock, Redis의 세 가지 방법이 나온다. 첫 번째 방법은 서버가 두 대 이상일 경우 유효하지 않고 데이터 측면에서 근본적인 해결책이 아니기도 하다(@Transactional과 동시 적용 안되기도 하다). DB Lock은 비관적 락, 낙관적 락 등 총 세 가지 락을 소개한다. 데이터를 제어한다는 측면에서 근본적인 해결책이긴 하지만 재고를 조회하기 위해 DB를 거쳐야 한다는 측면에서 비효율적이라고 볼 수 있다. 반면 Redis의 경우 DB와 다르게 디스크가 아닌 메모리를 이용한다는 점과 해시 테이블을 사용해 싱글 스레드임에도 조회 성능이 좋다는 점에서 대안이 될 수 있다. Redis 분산락[1]을 구현하는 대표적인 Redis 클라이언트(라이브러리)로는 Spring Data Redis에서 기본적으로 제공되는 Lettuce(RedisTemplate 사용)와 Redisson이 있다. 단순 캐시 및 키/값 저장소로만 레디스를 사용할 경우 Lettuce(직접 Lock 로직 구현)로 충분하고, 단순 저장소를 넘어 동기화 및 안정성이 필요한 시스템(재고 차감, 결제 등)에는 Redisson을 사용하는 것이 좋다고 한다.
      • 별개로 멀티 스레드 관련 테스트 코드 작성하는 법이나 JPA 작성하는 코드를 본 점이 좋았다. DB Lock 관련해서는 JPA의 어노테이션을 사용했는데 생소한 코드였다.
    2. 실습으로 배우는 선착순 이벤트 시스템 (완료)
      • 재고시스템과 비슷한 쿠폰 발급 로직으로 동시성 문제를 해결하는 방법을 소개한다. 다만 앞선 강의와 다르게 타 로직에까지 영향을 미치는 경우를 가정한다(아래 최초 수도 코드 참고). 해결책으로 Synchronized, Redis, Kafka를 소개한다. 분산 환경일 경우 Synchronized 키워드는 동작하지 않기에 Redis가 대안이 될 수 있다. 하지만 만약 발급하는 쿠폰의 수가 많다면, 즉 DB의 처리량을 넘어선다면 문제가 될 수 있다. 이땐 쿠폰 발급의 2단계에서 정체가 일어날 것이고, 쿠폰 발급 외에 타 로직도 영향을 받게 될 것이다. 이에 대한 대안이 바로 Kafka다. 쿠폰 발급을 Kafka의 컨슈머에서 비동기적으로 처리함으로써 DB의 부하를 줄이는 방법이다. 다만 이 경우 Lock 범위 밖에서 쿠폰이 발급되므로 중복해서 발급될 수 있기에, Producer의 앞단에서 Redis의 Set 자료구조를 이용할 수 있다. 한편 조회시가 아닌 Consumer에서 발급시 문제가 생길 수도 있다. 이에 대한 대비로 try-catch문으로 에러 로그를 따로 저장해주고, 추후 Batch 등으로 처리할 수 있다.
      • Kafka 사용시 도커 컴포즈, Zookeeper 등의 개념이 나와서 익숙치 않았다.
// 최초 수도 코드
쿠폰 발급() {
  // 1. 남은 쿠폰 조회(JPA의 COUNT 메소드)
  // 2. 쿠폰 발급
}
  • 레디스
    1. 개발자라면 알아야 할 Redis 기본 (완료)
      • 동시성 관련 강의에서 Redis를 접하고 좀 더 알고 싶어 수강했다. 코딩 강의에서는 자바 클라이언트로 레디스를 제어했으나, 이 강의에서는 cli를 통해 직접 Redis의 특징에 대해 설명했다. Redis는 리눅스 기반에서 동작하다보니, 도커를 통해 설치 후 테스트했다. 레디스의 성능이 좋은 이유, 자료구조 및 각 자료구조의 활용에 대해 설명했다. 몇 가지 적자면(잘 기억이.. 쓰게 되면 찾아봐야 된다), 레디스 한 개의 인스턴스는 0~15까지의 논리 DB를 제공한다. 레디스의 List 자료구조는 타 언어의 그것과 다르게 Deque 구조다. 빈번하게 변경되는 객체값을 캐싱할 경우 파싱이 불필요한 Hash를 사용한다. 이외에 메세징 기능으로 레디스를 사용할 경우 Pub/Sub을 지원하는데 발행된 메세지는 휘발되기 때문에 Streams도 언급한다. 근데 이걸 쓰느니 Kafka를 쓰라고..
    2. 실리콘밸리 엔지니어와 함께하는 Redis(진행중)
      • .
  • 카프카
    1. 카프카 완벽 가이드 - 코어편(진행중)
      • .
  • 인프라
    1. 따라하며 배우는 도커와 CI 환경
    2. 이론과 실습으로 실력이 높아지는 대세는 쿠버네티스
      • .
  • 리액트
    1. Spring Boot와 React로 배우는 초간단 REST API 게시판 만들기 (완료)
      • 간단한 예제로 React와 Spring 연동 연습할 수 있다. React를 쉽게 이해하기 위해 익숙한 게시판 예제의 짧은 강의라 선택했다. 쉽게 들을 수 있는 난이도지만 언어 문법에 대해 다시 리마인드해볼 수 있는 기회였다. 예를 들어 클라이언트단에선 ES5에서 도입된 함수형 메소드 map, filter, forEach 등을 오랜만에 접하였고 (배열의 각 요소 순회) , ES6에서 도입된 Array.from 같은 유사 배열 객체 혹은 이터러블 객체를 배열로 변환하는 메소드에 대해서도 공부할 수 있었다.한편 react-router-dom을 이용해 클라이언트 사이드 라우팅을 하는데, 구버전이라 문법이 최신과는 좀 달랐다. 이 외에 서버단에서도 JPA를 사용했기에 자바8 문법인 Optional을 통해 선언적인 return문을 작성하였고, Spring Data JPA의 Paging 기능 또한 상기해볼 수 있었다.
    2. 웹 게임을 만들며 배우는 React (진행중)
      •  
  • 토이프로젝트
    1. 견고한 결제 시스템 구축
    2. 웹소켓/STOMP 채팅서비스(Spring, Vue, Redis) (진행중)
      • 채팅 서비스 및 레디스의 활용에 대해 호기심이 생겨 수강했다. 강의를 따라 구현하진 않았지만 지식들을 정리해보는 계기가 되었는데, 예를 들어 강의에선 핵심 기술인 WebSocket, Stomp, Vue, Redis 이외에 Docker, JPA, Spring Security 등의 기술들이 가볍게 사용되었다. 채팅 서비스는 누가 메세지를 보냈는지를 구분해야 되다보니 회원 서비스가 필요하여 Spring Security가 들어갔고, 분산 서버로 구축하기 위해 토큰 (JWT) 인증 방식을 사용했다. 다만 강의에서 세션 관리는 비활성화해주었으나 폼로그인 방식을 명시적으로 비활성화해주지 않아서 좀 의아했다. 또한 컨트롤러를 통해 커스텀 로그인을 구현하는데, 이때 UserDetailsService를 사용하는 것이 아니라 MemberService(MemberRepository)를 사용한다. 이 부분에서 시큐리티를 이렇게 사용해도 되는건가 하는 의아함은 들었다. MemberController에서  AuthenticationManager를 호출해주어야 커스텀 로그인에 시큐리티 인증 체계를 통합하는 게 아닌가 하는 생각.
      • 또한 WebSocket(혹은 STOMP) 같은 기술들을 스프링 시큐리티와 어떻게 함께 통합하여 사용할 수 있는지도 생각해볼 수 있었다. HTTP와 다른 양방향 프로토콜이다보니 스프링 시큐리티 필터 체인을 타지 않는데, 이 경우 메세지 송신자를 구분할 수 있는 방법에 대해서도 생각해볼 수 있었다. 최초 웹소켓 통신시 HTTP 메세지를 전송하게 되는데 이때 HandshakeInterceptor에서 헤더의 토큰을 꺼내 인증 정보를 확인할 수 있다(보통 연결 거절시 사용)[2]. 만약 매 메세지마다 송신자를 표시해야 한다면 ChannelInterceptor에서 인증 정보 세팅해주면 메시지 핸들러에서 Principal 받아서 사용할 수 있다(@MessageMapping에서 Principal 파라미터 사용).
      • 외에 CORS, CSRF, XSS 등도 언급되는데 개념은 대충 알고 있으나 CORS 외에는 프론트단에 설정되는 거 같아서 좀 더 공부해야 한다. 외에 강의만 듣다보니 JPA로 테이블 하나 CRUD하는 거에만 익숙해졌는데, 조인해서 꺼내오는 부분이 

 

 

-----

1. SETNX

-- 원자성 보장O
SET lock_key unique_value NX PX 10000

-- 원자성 보장X
SETNX lock_key unique_value
EXPIRE lock_key 10

2. 스프링 시큐리티, 즉 HTTP 요청의 Principal과 웹소켓 요청의 Principal은 타입은 같지만 같은 인스턴스가 유지되는 것이 아니다.