데브코스 백엔드 3기 57일차

목금!
SpringData JPA를 배우고 간단한 주문 API를 만들어보았다
RESTDOCS를 사용해서 문서화까지 배워보았다
SWAGGER를 사용해본적이 있었는데 RESTDOCS가 운영코드와 분리가 되어 현재 현업에서 많이 쓰고있다는 사실을 알았다!


SpringData JPA

  • JPA를 추상화해둔
  • boot의 auto-configuration 덕분에 DataSource, Entity Manager, TransactionManager 설정 자동으로
  • JpaRepository 구현체로 repositoroy 접근 쉬워짐
  • @Transactional 사용해서 transaction, persistence context 관리 도와줌
    (transaction.begin(), commit(), entitymanager.persist() 등 생략가능)


  • Query
    • 쿼리메소드 : 명시된 keyword로 메소드명 만들어서 쿼리생성
      • 복잡한 조건 사용하려면 메소드의 길이가 길어지는 단점
    • 커스텀쿼리 : 복잡한 조건을 @Query("쿼리문")로 native query
      -> SQL과 유사한 JPQL(엔티티 객체를 대상으로 쿼리를 수행) 객체지향 쿼리 언어를 통해 복잡한 쿼리도 처리가 가능
      • JPQL(Java Persistence Query Language) : 객체를 대상으로 하는 쿼리문, SQL을 추상화해서 사용 => 어떤 DB를 사용하더라도 가능
    • QueryDSL : queryFactory를 만들어서 객체의 chaining 방식으로 쿼리(현업에서 많이 사용중)
      • 쿼리문을 소스코드를 사용해서 작성 -> 오타 등의 경우 컴파일 에러 발생
      • 조건문을 사용한 동적 쿼리문 작성이 간편


Tip!

  • Entity를 Transaction이 묶여있지 않는 밖까지 끌고 나가는건 좋지 않다
    • 왜?
      • Entity는 제 RDB와 묶여있는 영속화된 객체, RDB와 통신하는 객체
        => Entity가 Transaction 관리하지 않는 영역까지 빠져나가게 되면, 예상치 못한 곳에서 쿼리가 나가면 문제 있을 수!
        = 원치 않는 곳에서 Entity가 조작되는걸 방지
        => Entity가 관리되는 부분을 layer로 묶어두고 그 외의 layer에는 dto객체 만들어서 통신하는게 좋음
    • ex) Service layer에서 save 후 Entity 반환? No!
      • Entity의 id만 반환해도 id 통해 find 하면 됨 or dto 반환해주기



RESTDOCS

문서화 툴

MockMvc를 이용한 Controller layer test

  • restdocs dependency
    -> spring-restdocs-mockmvc
    -> mock mvc 쓸 수 있음
    -> boot 사용하니까 @AutoConfigureMockMvc
    -> @Autowired MockMvc mockMvc
    => mock mvc를 이용한 REST 호출 테스트 쉽게 가능


  • MockMvc의 perform() 통해 어플리케이션의 end-point 테스트, 얘를 호출할거다


RESTDOCS의 장점

  • 문서 & API가 일치하지 않으면 에러
    => 늘 문서가 API와 일치되도록, 최신화가 될수 밖에 없음
  • 테스트 코드를 작성해서 Controller layer까지(이 API가 정상 작동하는지) 테스트 할 수 있음


Swagger의 단점

  • production 코드와 분리가 안됨 = 운영코드 상에 document화를 위한 코드가 생김
    -> 섞여있음
    => 해석 어려움, 유지보수 어려움


RESTDOCS 사용하기

빌드와 엮어서 플러그인 실행하게해서, html 파일 만들고 이걸 static resource를 서빙할 수 있는곳(NGINX 같은)에 올려두고 API로 문서공유하는 방법 많이 사용

  • restdocs 문서화 plugin 추가
  • @AutoConfigureRestDocs
  • RestDocumentationResultHandler의 document() 사용
  • document(“identifier(=이름, 어떤 snippet으로 떨어트릴지, ex) order-save)”, requestFields(), responseFields())
    => target의 generated-snippetsorder-save 폴더에 들어가있음
    => 이걸 docs의 asciidoc의 index.adoc에(mustache 문법)
    => asciidoc 플러그인 실행하면 -> target의 generated-docsindex.html 생김



이번주 테코톡

12/5 월, 우기의 MySQL 아키텍처, 릭의 MySQL 아키텍처

MySQL 엔진(두뇌느낌 - 클라이언트 접속과 SQL 요청 처리)
Query Parser → Preprocessor(전처리기) → Optimizer → Query Execution Engine

  • Query Parser : SQL 문장을 의미있는 단위의 토큰으로 쪼갬, 트리로 -> Parser Tree
  • Preprocessor : Parser Tree기반으로 쿼리문장에 구조적인 문제점이 있는지 검사(토큰 하나씩 검사해서 토큰에 해당하는 테이블 이름이나 컬럼이 실제로 존재하는지 등)
  • Optimizier : 요청된 SQL문을 최적화해서 실행시키기 위해 실행계획을 짜는 중요한 역할
    (규칙 기반 vs 비용 기반(통계적인 방법))
    -> MySQL 엔진은 옵티마이저가 작성한 실행계획에 따라 스토리지엔진을 호출(핸들러 API사용해서)해서 쿼리실행


MySQL 스토리지 엔진(손과발 느낌)

  • 데이터를 디스크에 저장 or 디스크에 저장된 데이터 읽어옴
  • MySQL 8.0부터 컴포넌트형태(플러그인 형태였음)
  • InnoDB / MyISAM
    ⇒ MySQL 8 이상부터는 MyISAM의 공간 좌표, 전문 검색 기능을 InnoDB도 지원
    ⇒ MyISAM 에 대한 성능 및 기능 개선이 이루어지지 않고 있어 InnoDB가 강세


InnoDB

  • PK를 통한 클러스터링 (읽기는 빠르나 쓰기 연산은 오래 걸림)
  • 트랜잭션 지원
    • InnoDB 버퍼풀 : 변경된 데이터를 디스크에 반영전까지 잠시 버퍼링
    • 언두로그(un-do log) : 변경전의 데이터를 백업해두는 공간
      -> rollback 시 언두로그에 백업된 데이터로 복원
    • 리두로그(re-do log) : 변경된(커밋완료된) 데이터 백업
      -> 영속성 보장 / 서비스 비정상 종료 시 리두로그에 백업된 데이터로 복원
    • MVCC(Multi-Version Concurrency Control) : 설정된 트랜잭션 격리레벨에 따라 조회데이터 달라짐 이 기술이 MVCC
      (= 레코드에 락 걸지 않고도, 다양한 버전이 동시에 관리된다는 뜻)
    • 예를 들면 트랜잭션 격리레벨에서
      수정전의 데이터를 읽어오게 한다면(READ_COMMITTED) 커밋전이기 때문에 언두로그에 있는 데이터를,
      수정중인 데이터를 조회하게 한다면(READ_UNCOMMITTED) 버퍼풀의 데이터이터를
    • 레코드 단위로 락(MySQL에서 사용할 수 있는 스토리지 엔진 중에서 거의 유일)


MyISAM

  • 클러스터링, 트랜잭션, FK 지원 X
  • 테이블 단위 Lock
  • 키 캐싱


12/6 화, 매트와토르의 MySQL 성능 최적화

아직 생소해서..! 한두번 더 들어야 할듯 하다 어려웠다!

  • 인덱스가 무엇일까 → 조회성능을 개선하기 위함
  • full table scan하는 경우 : 인덱스가 없는 경우, 데이터가 개수가 적은 경우, 읽고자하는 데이터가 1/4이상인경우
  • 커버링 인덱스 → full scan시 모든 인덱스의 컬럼을 읽기위해 생기는 disk i/o를 줄이기 위해 인덱스로 설정한 컬럼만 읽는다


  • Index Condition Pushdown : MySQL이 인덱스를 사용하여 테이블에서 행을 검색하는 경우의 최적화 의미

  • 검색시 InnoDB에서 먼저 꺼내오고
    Mysql엔진이 where절에 대해서 추가 연산을 하는데 이는 disk I/O가 너무 커짐
    => 그렇기 때문에, 복합 인덱스를 사용하여 where절의 조건을 복합인덱스의 키로 사용
    (복합인덱스는 정렬된 경우에만 사용하자)

    • Index column만을 사용하여 where조건의 일부를 평가할 수 있는 경우
      MySQL엔진은 where조건 부분을 스토리지 엔진으로 푸시함


12/7 수, 찰리의 인덱싱, 리차드의 @Transactional

  • Transactional annotaion → proxy 객체가 bean으로 등록
  • cardinality
    • 상대적인 개념
    • distinct 값이 많으면 중복도가 낮다 = 원소의 종류가 많다 = 카디널리티가 높다
    • Index 선정 기준 → 카디널리티가 높고, where절에 자주 쓰이냐 등등


12/8 목, 카일의 데이터베이스 락, 오즈의 데이터베이스 락

  • 데이터베이스 : 데이터를 저장하고 있는 프로그램
  • 락 : 데이터에 접근하지 못하도록 막는 장치


  • Optimistic
    • version 사용해 관리
      • DB에 락 안걸고 버전이라는 컬럼 하나로 관리 -> 어플리케이션 레이어에서 거는 락
    • 기본적으로 충돌이 안 일어날거라는 생각(긍정적)으로
      • 그렇지만 나면? 충돌방지 위해 Optimistic lock Exception
    • 실제 DB에 락을 걸지 않기 때문에 데드락 적음, 충돌이 빈번하지 않으면 성능 좋음
    • 충돌이 발생하면 오버헤드(수정시 충돌 발생하면 다 롤백하는게) -> 요즘은 많이 좋아짐
      • 내가 v1에서 열심히 수정했는데 그 사이에 다른 누군가가 v1 이미 수정해서 v2로 올라가있어
        근데 나는 그 사실을 모르니까 커밋하려고 하면 그제서야 충돌 알고ㅠ 여태까지 내가 한게 다 롤백..!


  • Perssimistic
    • 기본적으로 데이터 갱신 시 출돌발생할거다 생각(비관적)
      -> 우선적으로 조회할 때부터 DB에 락 걸음 -> 하나 조회하는 중에 다른거 조회 시도하면 웨이팅시간
    • 장점 : 무결성의 장점(얘만 조회할 수 있으니까)
    • 단점 : 데드락의 위험성, 충돌이 없으면 오버헤드(락 걸고있는거 자체가 비용이니까)
    • Shared Lock(S락) : 다른 사용자가 읽기만 가능, 수정삭제 불가능
    • Exclusice Lock(X락) : 다른 사용자가 읽기조차 못함, 읽기수정삭제 다 불가능 = write에 대한 락


  • Optimistic vs Pessimistic
    • 충돌 자주 발생하는가 -> Pessimistic
    • 읽기 / 쓰기 비율 -> 수정이 많다? Pessimistic, 근데 요즘은 Optimistic도 수정 시의 오버헤드 많이 좋아짐

    ⇒ 일반적인 웹 어플리케이션은 읽기가 대부분 -> Optimistic lock 사용


  • 데드락이 생기는 경우
    • 서로 참조하는 테이블이 x락을 걸 경우


12/9 , 둔덩의 교착상태, 케빈의 Deadlock

  • 교착 상태란?
    • 프로세스나 쓰레드들이 자신이 가진 자원을 내어놓지 않으면서
      서로가 가진, 자원을 기다려 무한 대기에 빠진 상태
  • 데드락 탐지 : 데드락의 존재 여부 및 데드락에 연관된 자원과 프로세스를 알아내자!
    (순환대기 존재 여부에 초점)
    • 자원 할당 그래프 알고리즘 - 순환 사이클의 존재 유무를 체크
    • 해결 방법
      • 프로세스 종료 : 교착 상태의 프로세스 모두 중지 or 교착이 제거될 때까지 하나씩 제거
      • 자원 선점 : 다른 프로세스에게 먼저 할당
  • 데드락 복구 : 순환 대기를 깨서 데드락에서 회복
    • 희상자 선택 : 시스템마다 우선순위의 기준이 다름 → 남은 수행 시간, 자원 유형의 수
      • 트랜잭션 타임 아웃시 교착 상태든 아니든 가장 작은 트랜잭션 롤백
      • 트랜잭션 크기는 삽입, 업데이트 또는 삭제 된 행 수에 의해 결정
    • 롤백
    • 기아 상태



일기(회고)

  • 데브코스 시작하면서 계속 하겠다던
    CS공부와 알고리즘,, 두달이 다되어가는데 소홀했다
    반성만 매번하다가 이제 드디어 시작했다!
    데브코스 적응과 과제 핑계는 이제 불가능!


  • 데브코스를 하면서 기대했던 부분은 세가지였다
    동료, 멘토제도를 통한 현업파악과 코드리뷰, 코어타임이 있지만 자습(혼자 또는 같이)을 권장하는 커리큘럼
    예상했던 대로 잘 충족이 되고있다 갑자기 이 얘길 왜 하냐면
    • ㅌㅅ이와 ㅇㅂ이가 BFS, DFS를 설명해주었다
      계속 이해가 안가던 부분을 물어보면서 설명을 여러번 들으니까 헉!했다
      드디어 이해가 가서ㅠ 너무 짜릿했어
      너무너무 고마웠다 최고ㅠ
    • 여태까지 데브코스 강의와 과제에 더 신경을 썻었다면
      앞으로는 코어타임과 그 외의 시간에 내가 하고싶은, 궁금한 부분과
      취준에 필요한 공부도 더 하겠다고 한번더 다짐~
    • 멘토님들테도 더 많이 물어보자 데브코스를 열심히 이용해먹자..(?)


  • CS 스터디 발표를 했다!
    팀원들테 내가 생각하지 않았던 부분들을 질문을 받으니까 좋았다
    예를 들면 나는 HashTable과 HashMap의 성능이나 차이가 궁금해서 조사했다면
    질문은 HashMap과 HashSet의 성능차이가 들어온다던지?


  • 12월이 되었으니 겨울로 꾸며보았다(곧 크리스마슈)
    다음은 벚꽃으로 꾸미고 나면 데브코스가 끝나겠구낭(갑분아련)

    1207


업데이트: