데브코스 백엔드 3기 76일차
화수! 외에는 복습 및 휴식으로 강의 없음!
다음주부터 시작될 팀프로젝트를 대비해
프로젝트 시작 전 알고 있으면 좋은 것들에 대해 배웠다
일기(회고)
- 반성을 좀 하는 1주일 겸 행복했던 1주일이었다
데브코스 복습겸 휴식이라고 쓰고 방학이라고 읽는다ㅎ- 연말이고 해서 보고싶었던 사람들을 많이 만났다
힐링되었고 행복했다
추진력을 얻기위한 힘을 누적했다고 생각하고
이제부터 또 달려야지 - 그래도 2022를 즐겁게 보내주고 2023년도 즐겁게 맞이해서
기분은 좋음! - 개인적으로 22년은 개발공부를 시작한 해로,
나에게 새로움 많았던 해기 때문에 한 해 회고를 도전해볼것
- 연말이고 해서 보고싶었던 사람들을 많이 만났다
- 계획한 양만큼의 복습을 하지 못했고
네트워크 공부를 손도 대지 않았다 반성할것
반성은 하되, 자책은 하지말자 행복했음 되었다 그럴 시간에 움직이자
그러니까 결론은, 다음주에 조금 더 분주하게 움직일 것!- 이번주 게더 사진조차 없다..!
- kakao tech 영상에서 JVM warm-up 영상을 봤는데 흥미로웠다
JVM에 대해 공부해볼 것
프로젝트 시작 전 고려할 사항들
Github organization plan
- free / team / enterprise
Member Privileges
: Base permissions 미설정된 repo에 어떤 권한 가질지- No permission / Read / Write / Admin
- 보통 Read로 두고 repo 단위로 별도 권한 부여
- Read : push 안되니까 fork해서 PR
- Write : push 가능
- Admin : collaborator 추가 가능
Team
설정- repo collaborator 추가 시 유저단위보다는 team 만들어 단위로 추가하기
- Member Base permission을 No permission으로 두고 team에 넣어 권한주기도 함
- CVCS(Centralized) 중앙집중식 버전관리 시스템 vs DVCS(Distributed Version Control System) 분산 버전관리 시스템
- Git은 DVCS에 속함
작업관리도구 Issue Tracker
JIRA
: 자유도 높음(property 추가) / 10명까지 무료 / 관리자가 좋아함Github Projects + Issue
- 커밋메시지에 이슈번호 남기면 자동으로 링크됨, PR review의 comment를 바로 issue로 만들기 가능
- 무료
- 개발자가 좋아함
- 속도빠름, 직관적
- 단점 : issue 개별 due date 설정불가 -> milestone 만들어서 due 설정 후 issue가 이걸 설정하게 만들어야함
YouTrack
: 최근 툴
작업방식 workflow
foring workflow
: fork한 repo에서 작업하는 것(권한제어 잘하면 feature branch workflow 사용)feature branch workflow
: fork하지 않고 원본 repo에서 branch 따서 작업하는 것- 1)organization 생성 + Member privileges 설정
- 2)team 생성
- 3)repo마다 branch protection rule 설정 + 권한필요한 팀 추가
데이터 직렬화 포맷
xml
yaml
JSON
: 자바스크립트에서 객체를 명시하는 문법으로 시작한 개념- client -> server : 객체로 만드는 디코딩 비용
- client <- server : Json 형태의 문자열로 만드는 인코딩 비용
- 데이터가 많아지면 이것도 병목의 원인이 될 수 있음
- 요즘 client-side rendering 사용
- 페이지 일부 변화가 많으니까
클라우드
- 클라우드 : 서버 컴퓨터 돌리는
- 쓴 만큼만 과금 + 리소스 무한정 늘릴 수 있음
- 인프라 구성시 제일 먼저 생각해야 하는거 : 컴퓨터 엔진
- AWS
- 얼마나 많은 부분을 추상화 했느냐에 따라
- EC2
- ECS
- ECS + Fargate
- Lamda
- 얼마나 많은 부분을 추상화 했느냐에 따라
Lamda
: 1개월당 100만 request 무료(코드 실행시간으로 계산)- EC2는 컴퓨터 한대 빌리는 개념 -> 켜져있으면 과금
코드 실행시간
을 어떻게 따지지?serverless 개념
사용해서실행시간
이 늘어나지 않으면 과금 안됨- 서버 늘리는 것도 CPU사용량 몇퍼센트 넘어가면 자동으로 늘려주는(Auto Scaling)걸로 자동 탑재되어 있음
- 매우 추상화 되어있음
- AWS가 서버 많이 띄우고 이사람거 저사람거 다 거기에 돌림
DB (RDB / NoSQL)
- NoSQL은
RDB의 한계를 극복
하기 위해 사용하는 것- 대부분의 도메인은 schema가 정해진 데이터 다룸
- NoSQL의 장점이
schemaless
인데, 이 장점을 사용하지 않게되니까 RDB 쓰는편이 좋음
- NoSQL의 장점이
- 대부분의 도메인은 schema가 정해진 데이터 다룸
- MySQL / Oracle / PostgreSQL
- MySQL과 호환되는 Aurora도 있음(Amazon에서 만든 DBMS)
- DB도 서버 띄우기 -> DB전용 서버
- ex) Amazon RDS
- 사용할 수 있는 DB 한정적 -> Aurora는 Amazon에서 만들었으니 가능
- ex) Amazon RDS
Alter Table문
Alter Table
문 : 오래걸림 + 테이블 전체에 lock 발생
=> 해결 :Online DDL
- 테이블에 lock 일으키지않고 alter table문 실행함
- copy해서 새로운 테이블 만들어서 alter table 동작 후, 참조만 바꿔치기
- 그동안의 새로운 데이터들은 로그를 따로 모아둠
- 참조 바꿔칠때만 잠시 lock
index
- 데이터가 어떻게 저장되는지에 따라
- clustered : pk 기준으로 정렬해서 저장 - 물리적 저장
- non-clustered : 별도의 공간에 인덱스내용 저장(fk, uq) - 논리적 저장
- Where 절에 자주 쓰이는 + 카디널리티 높은(중복 낮은) 컬럼으로 설정하기
- Tree같은 비선형 자료구조 사용
- index 타는 쿼리 : select 시 O(1)
Like ~%
는 인덱스 탐 /Like %~
orLike %~%
는 안탐
Table 만들기
- Table 잘 만들어야함!
- 쿼리속도가 높아지고, 여기에 붙는 쿼리 작성도 쉬워짐
Data Type
잘못 선택 시 -> 쿼리 느림 + 용량 낭비
1. 문자열 CHAR vs VARCHAR
- 명시된 최대길이(ex) 100)보다 작은 문자열(ex) 10)이 들어오면
CHAR
: 100만큼 용량 점유VARCHAR
: 10으로 줄이고(resize) 용량아낌resize
과정 -> insert 시간 늘어남- resize 된다고 큰값 쓰지말고 가능한 작은거 쓰자
(너무 크면 index 등록안됨)
- 길이 편차 작은 주민번호, 핸드폰번호, 비밀번호 암호화 후 -> CHAR(max 255)
- 길이 편차가 크다 or 256 이상 쓰고 싶다 -> VARCHAR
2. 정수 TinyInt(1) / SmallInt(2) / MediumInt(3) / Int(4) / BigInt(8 byte)
- 나이 같은거에 TinyInt 쓰면 storage 아낄 수 있음
- signed
- type 뒤 unsigned 붙이면 -> 음수표현 위한 비트 아낌 + 양수 범위 2배로 늘어남 = maximum value 확장
- ex) Auto Increment PK 사용시 유용
- type 뒤 unsigned 붙이면 -> 음수표현 위한 비트 아낌 + 양수 범위 2배로 늘어남 = maximum value 확장
- Int(11) : 괄호안의 숫자는 zerofill(0 어디까지 채울지) option시에만 적용됨
3. boolean
쓸 수 있지만, 사실 DB엔 TinyInt(1)로 치환됨
- 만약 0,1만 허용 원하면 Bit(1) 쓰는 것 추천
4. 시간 datetime / unix timestamp
- datetime
- 저장 시 어느 timezone 따를지 - UTC기준 추천
- unix timestamp :
2023-01-03 09:00:00 UTC
- 1970년 이전 못함
- 표준
- 이메일 : VARCHAR(320)
- 주민등록번호 : CHAR(13)
API Specification
- Web Service에서의 API : Http networking 통해 사용할 수 있는 API = HTTP API
- end-point 분리해서 많이 사용
- HTTP API 디자인할 때 사용하는 가이드라인 중 하나 : REST
API 디자인 방법론
SOAP
- legacy
- Http 위에서 돌아가는 또 하나의 protocol 개념
- Http 위에서 돌아가니까 Http 생으로 쓰는것보다 훨씬 느림 + 까다로움
- protocol 개념이라 챙길게 많음
REST
- Http API 디자인 가이드라인 개념
- 가이드라인 개념이라 챙길게 없음(관련 지식 + web server framework만 있으면 됨)
- resource마다 CRUD에 맞추어 end-point 하나씩 있음
- Http API 디자인 가이드라인 개념
GraphQL
- end-point 하나 + client는 자신이 원하는 데이터를 query param(GraphQL)에 명시 -> GraphQL에 대응만
Http method semantic
멱동성 idempotence
: 2번이상 요청 시 side effect 동일하면(= 데이터의 상태가 동일하면) idempotence하다고 표현- idempotent : Get(2번 조회해도 같음), Put(delete 후 insert), Delete
- not idempotent : Post(2번 생성하면 다름), Patch(update)
Header
- request
Accept-Language : ko
- value에 해당하는 언어에 맞추어 컨텐츠 제공
Accept-Encoding : gzip
- Client가 해석할줄 아는 압축알고리즘 적어둠
= 응답 줄 때 이 압축알고리즘 사용해줘 요구 - (response payload 압축해서 내려받아야 네트워크 비용 아낌)
- Client가 해석할줄 아는 압축알고리즘 적어둠
- response
Location
- post 성공 시 생성된 resource의 url을 제공하는게 좋음 (+ 201 created code)
Content-Disposition : attachment; filename = ""
- 다운로드되는 파일의 이름을 설정
이번주 영상
kakao tech - JVM warm up / if(kakao) 2022
실제 일어났던 이슈와 그에 대한 해결책을 찾는 과정을 보여줘서 너무 유익했던 영상이었다
- java :
source code -> (compile) byte code -> JVM에서 interprete -> machine code
- 장점: 독립적 (byte code -> 자바실행 가능한 환경이면 빌드 다시안해도 사용가능)
- 단점 : compile + interpreter 언어 -> 느림
- 보완 : JIT(Just In Time) compiler
- C++ :
source code -> (compile + optimization) machine code(program)
- 장점 : 훨씬 빠름
- 단점 : 빌드환경 CPU아키텍처에 종속적 -> 다른곳에서 쓰려면 빌드 다시해야함
JIT
적시에 기계어를 만들어냄을 의미
-
byte code -> machine code로 변환 시,
machine code를 cache에
저장
-> 반복되는 기계어 변환을 줄임
-> 성능향상 + 런타임 환경에 맞추어 코드 최적화(또 추가적 성능향상됨) -
그럼, application 시작시엔 cache 비어있어 성능 도움 안되겠는데?
- 그래서 시작 후,
의도적으로 미리 로직
실행
-> 기계어가 cache에 저장되고 최적화 될 수 있는warm up 절차
필요
- 그래서 시작 후,
Latency 이슈
카카오 T계정 서버 배포 중 초기응답 지연문제
발생(트래픽이 많지 않은데도)
-> 병목
을 찾자!
- 외부 데이터베이스 지연 없었음
- application 영역(도메인 로직에 대한)의 지연 없었음
- Tomcat Web Application의 Thread 개수 : 10~8192로 설정되어 있었음
- Thread 시작 개수 조정 필요 : 200개로
- DB연결은 RDB의 connection pool이 20개로 시작되도록 설정되어 있었음 + 서버 시작 이후로도 큰 변화 없었음
= 문제 없음 - 계정 API의 JVM warm up이 잘 준비되었는가
- warm up 동작
- kubernates liveness/readiness probe 요청
-> liveness/readiness 요청 처리하는 컨트롤러에서 warmer() 호출
-> warmer()에서 데이터베이스에 정해진 정보를 지리하도록
- kubernates liveness/readiness probe 요청
- 실서비스에서 사용하는 API가 아니었음 & 특정 데이터조회 로직에 한정
= 충분한 warm up과정이 이루어지지 않고있다고 판단
=> 실제 사용하는 API를 localhost로 호출하되, real traffic과 유사한 형태되도록 개선 필요
- warm up 동작
- Thread 시작 개수 200개로 조정
- warm up은 각 pod마다 localhost로 API 요청하도록 변경
- 실제 API요청과 동일한 응답코드로 처리되도록 호출
- 대부분의 GET API 포함(특히 서비스에서 자주 사용되는 API들)
- 이전에는 정해진 시간만큼만 지연시키고 traffic 인입시켰다면
이제는 warm up이 완료되어야 traffic 인입되게 개선
=> 해결!
2달 후 또 발생
warm up count
늘리기- 실제 트래픽과 같은 많은수의 warm up 시도
=> 내부 재연상황에서 응답지연문제 해결!
- 실제 트래픽과 같은 많은수의 warm up 시도
=> 왜 해결되었지? JIT 내부에 대해 알아보자!
JIT 내부
-
JIT는 메서드 전체단위로 컴파일함
= 메서드 내 모든 바이트코드는 한꺼번에 네이티브 코드로 됨 -
Tiered compilation
이라는단계적 컴파일
통해 코드 최적화함- 메서드가 정해진 임계치만큼 호출되면 C1 단계로 최적화
C1
: 간략한 최적화- 또 임계치 넘게 호출되면 C2 단계로 최적화
C2
: 최대 최적화 -> 코드캐시에 저장, 활용 -> 코드의 실행속도 높임
=> JIT는 단계별컴파일을 진행하니까
메서드가 C2 compiler를 통해 최대최적화
될 수 있도록 충분한 warm up
시도를 하자!
- 참고) cache full messgae
- code cache 가득참 의미
-> 성능상 이득 기대 못함 -> 크기 늘려주기
- code cache 가득참 의미