// 에드센스

 

를 읽고 나눠보면 좋은걸들 정리

목차

  • 자라기
  • 함께
  • 애자일

 

 


자라기

당신은 몇 년차?

 
 

 

무엇이 소프트웨어 기술자의 등급을 판가름할까?

  • 한국소프트웨어산업협회에서는 [학력 + 경력 + 자격]을 본다

 

 

 

경험이 길수록 잘하는 개발자일까?

  • 그렇지 않다
  • 경력 연차만으로 이 사람이 초급인지 고급인지 알 수 없다

 

그렇다면 직원을 뽑을때 무엇을 기준으로 그 사람의 실력을 예측할 수 있을까?

  • 존 헌터와 프랭크 슈미트의 연구
    • 채용시 가장 효과적인 예측변수가 무엇인지?
    • = 즉, 사람을 뽑을때 무엇을 봐야 잘 뽑았다 소문이 나는지에 대한 연구
    • = 채용시 선발 여부를 고려하는 변수와 직무 성과라는 변수간에 상관성에 대한 연구

 

상관성이란

  • 하나가 변하면 다른 하나가 변하는지 안변하는지
    • 예를들어
      • 부모의 경제수준과 자녀의 학업성적은 상관성이 높다
      • 부모의 머리카락 길이와 자녀의 학업성적은 상관성이 낮다
  • 상관성 지표는 다음과 같이 해석할 수 있다
    • 0.5 이상 - 높은 상관성
    • 0.2 ~ 0.5 - 중간 상관성
    • 0.2 이하 - 약한 상관성

 

 

연구결과

우리가 높을것이라 예상했던 예측변수의 상관성

  • 연차 - 0.18
  • 학력 - 0.10

 

상관성이 높았던 예측변수

  • 작업 샘플 테스트 - 0.54(채용 후 할 작업의 일부를 테스트하는것(과제전형느낌))
  • 지능테스트(아이큐테스트같은거) - 0.51
  • 성실성, 꼼꼼함 - 0.41
  • 레퍼런스 체크 - 0.26

 

상관성이 매우 낮았던 것

  • 나이 - 0.02

 

저자의 제안

  • 행동중심의 구조화된 인터뷰
    • 예를들어
      • 개발자로서 철학이 무엇인가요? 같은 질문이 아닌
      • 지난 프로젝트에서 겪은 어려움과 해결방법에 대해 설명해주세요
  • 작업 샘플 테스트 (과제전형)
  • 짧은기간 같이 일해보기 (수습기간)

 

잘뽑는것보다 중요한것

  • 이미 뽑은 사람을 어떻게 할 것인지
    • 흔히들 채용에는 신경쓰지만 이후의 교육, 훈련은 고민하지 않는다
    • 마치, 운동기구를 사놓고 운동하지 않는 것
    • 전문성 관리를 개인에게만 맡긴 후 회사는 손을 떼고 하위10%는 해고하는것은 회사에게나 개인에게나 손해다

 

 

 

1만시간의 법칙?

 

 

  • 특정 분야의 전문가가 되려면 1만시간의 투자가 필요하다
  • 내 경력이 6년이고, 야근도 좀 했고, 계산해보면 1만시간이 넘었는데? 싶지만 이건 잘못된 계산이다
    • 우리는 어릴때부터 하루에 3번씩 이를 닦지만 우리는 이닦기의 고수라고 말 하지 못한다
  • 중요한 것은 의도적 수련
    • 악기 연주자들에게 공연은 의도적 수련이 되지 못한다
    • 개인기량 향상을 목적으로 하는 애쓰는 수련이 의도적 수련

 

이렇게 계산하면 터무니없이 많은 시간이 필요하게됨

  • 하지만 우리는 업무를 하면서도 의도적 수련을 할 수 있음
    • 애자일 철학을 활용하는 것이다
    • 실수를 교정할 기회가 있는것 + 피드백을 짧게 가져가는것
      • 골프 퍼팅연습을 하는데 공이 어디로가는지 보지않고 공만 친다? → 교정기회 x
      • 퍼팅의 결과를 1년뒤에 피드백해준다면 기억이 날까? “당신이 작년 이맘때 쳤던 공은 들어갔습니다” → 피드백 느림

 

 

 

 

당신이 제자리걸음인 이유

  • 실력을 높이기 위해서는 의도적 수련이 중요한데, 실력과 작업의 난이도가 비슷해야 한다.
    • 작업 난이도가 너무 낮으면 지루함을,
    • 너무 높으면 불안함/두려움을 느낀다.
  • 자신이 업무 시간 중에 불안함이나 지루함을 느끼는 때가 대부분이라면, 실력이 도무지 늘지 않는 환경에 있는 것이다.
  • 지루함을 느끼는 경우에는 조금 더 높은 수준의 업무에 도전하고, 불안함을 느끼는 경우에는 가장 간단하면서 핵심적인 결과물을 첫 번째 목표로 삼아 난이도를 낮추는 것이다.

 

 

 

이소룡의 이야기

 

 

 

 

의도적 수련

  • 의도적 수련을 위해서는 나의 실력과 작업 난이도가 비슷해야한다

 

  • 불안함과 지루함의 영역에서는 의도적 수련이 안된다
  • 가운데 영역에서만 의도적 수련이 된다

 

 

 

의도적 수련을 위해 몰입으로 가는 4가지 방법

지루함을 느낄때 a1 - 실력 낮추기

  • 작업 난이도는 유지
  • 실력을 낮추기
  • 팔다리에 모래주머니를 달고 달리기
  • 개발자라면, 보조도구 사용하지 않기(데이터그립같은거..?)

 

지루함을 느낄때 a2 - 난이도 높이기

  • 이소룡의 경우, 3분안에 적을 쓰러트리기
  • 개발자라면 하루분량의 작업을 한시간안에 하기
  • tps 개선하기
  • 코드리뷰 코멘트 평소보다 더 달기
  • 혹은 당장 안해도 되는 옵셔널한 일 하기
    • 리팩토링하기

 

불안함을 느낄때 b1 - 난이도 낮추기

  • 자신의 맡은일에서 핵심 기능만 구현한 아기버전 만들기 0.0.1
  • 테트리스 만들기가 어렵다면, 화면에 네모 하나만 그려보기
    • 자료구조나 회전알고리즘따위를 알고나서 구현하는게 아니다

 

불안함을 느낄때 b2 - 실력 높이기

  • 스터디하기
  • 잘하는 사람과 페어프로그래밍하기
  • 좋은 디버거, 분석툴 사용하기
  • 이전에 비슷했던 일을 했던 경험을 떠올려보기

 

의도적 수련을 위해 팀장이 할 수 있는 일

  • 몰입 영역 밖으로 몰아내는 행동을 하지않는다
    • 일이 너무 쉬워서 지루해하는 직원에게 컨퍼런스나 스터디를 시키는것
    • 일이 너무 어려워서 힘들어하는 직원에게 진행되지 않는 일의 분석 보고서를 제출하는 등 추가업무를 주는것

 

 

 

 


함께

소프트웨어 개발 비용을 차지하는 4가지 요소

품질 전문가 제럴드 와인버그가 쓴 책 Quality Software Management에서는 소프트웨어 개발 비용을 차지하는 4요소로 다음 것들을 정함

  • 도구
  • 사람
  • 시스템
  • 관리

 

이 중 무엇이 가장 큰 요소일까?

  • 모 대기업에서 설문조사한 결과
  • [관리 → 시스템 → 사람 → 도구] 순이었다
  • 하지만 보통 관리자들이 선호하는 개선순위는 역순이다

 

 

 

전문가팀이 실패하는 이유

  • 뛰어난 사람을 뽑아놓으면 잘할거라는 막연한 기대… 정말그럴까?
  • 가장 뛰어낫던 선수들만 뽑아서 만든 올스타팀은 성적이 그다지 좋지 않다(예시)
  • 스타들이 한명씩 팀에 추가될때마다 성적향상은 한계효용을 보이며 어느 수준을 지나면 음의 방향이 된다(팀의 성과를 깎아먹음)

https://blog.tanagement.co.kr/insight_management/?bmode=view&idx=14218037

 

[슬램덩크] 북산은 어떻게 산왕공고를 이길 수 있었을까 : 강점 리더십/경영

최근 3040 X세대의 추억을 소환하여 영화 '더 퍼스트 슬램덩크'가 열풍을 일으키고 있다. 필자도 옛추억을 소환하여 재미있게 다시 슬램덩크를 찾아보게 되었다. 그런데 10대 때는 느끼지 못했던

blog.tanagement.co.kr

 

 

 

 

 

이에대한 한 가지 실험

두가지 팀으로 나눔

  • 전문가들로만 구성된 팀
  • 전문가+비전문가로 구성된 팀

두가지 협력방법으로 나눔

  • 45분의 실험중 10분간은 어떻게 협력할지 계획을 세우도록함 (개입)
  • 45분의 실험 전체에 대해서 아무런 개입을 하지 않음 (개입x)

 

이런 상황에서 성과를 비교해보면 다음과 같다

 

 

 

주목할 부분은,

  • [협력한 비전문가팀][협력하지 않는 전문가팀] 보다 좋은 성과를 냈다는 것
  • 이유는 정보공유의 차이

 

정리하자면

  • 전문가만 모아 놓는다고 성과가 잘 나오는게 아니다
  • 정보공유하고 협력을 잘하기위해선 명시적인 도움이 필요하다
  • 소셜 스킬등이 뛰어난 제너럴리스트가 있다면 도움이 된다

 

 

 

 

구글이 밝힌 탁월한 팀의 비밀

  • 구글이 뛰어난 팀의 특징을 찾기위해 진행했던 프로젝트 “아리스토텔레스 프로젝트”
  • 연구결과 주목할 부분은
    • 팀에 누가 있는지(전문가, 내향/외향인, 지능)보다 팀원이 어떻게 상호작용하는지가 중요
    • 심리적 안정감이 큰 영향을 준다
    • 팀 토론등 특별히 고안된 활동을 통해 심리적 안정감을 개선할 수 있다

 

심리적 안정감이란

  • 내 생각이나 의견, 질문, 걱정, 실수가 드러났을때 처벌받거나 놀림받지 않을것이라는 믿음

 

팀 토론과 같은 특별히 고안된 활동?

  • 토론 주제를 안전한 환경에서 이야기하게 해주는것 자체가 심리적 안전감을 높일 수 있는것
  • 관리자가 매일매일 팀원들과 같은 상호작용에서 변화가 필요함
    • 일상적으로 일어나는 상호작용에는 변화가 없으면서 토론회같은 특별한 걸 한다고 하면 오히려 신뢰가 깎인다

 

 

 

쾌속 학습팀

패러다임 전환, 죽느냐 사느냐

  • PHP를 사용하던 회사에서 사장님이 컨퍼런스를 다녀오더니 갑자기 자바로 바꾸라고함
  • 어떤팀은 잘 바꿧지만 어떤팀은 잘 바꾸지 못했음
  • 왜일까?

 

하버드 비즈니스 리뷰에 심장수술에 대한 논문이 실렸음

  • 제목은 <팀 학습 속도 높이기>

 

새로운 방식의 최신 수술방법 “최소 심습 수술법”

  • 이를 도입한 두 병원을 비교함
    • 실선은 첼시아 병원
    • 점선은 마운틴 메디컬 센터
  • 두 병원 다 처음 수술법을 도입했을때는 수술시간이 6시간이었음
  • 하지만 횟수가 반복되자 마운틴 메디컬 병원은 3시간으로 개선됨
  • 주목할점은
    • 첼시아 병원의 리더는 저명한 심장외과의사
    • 마운틴 메디컬 센터의 리더는 경험이 부족한 젊은 외과의사
    • 즉, 리더의 기술적 깊이는 팀 학습속도에 영향을 크게 줄 수 없다

 

리더가 팀 학습 속도에 미치는 영향

  • 기술적으로 탁월한 리더보다다는 학습 환경을 만들 수 있는 리더가 중요

 

학습 환경의 차이

  • 마운틴 메디컬 센터는 팀원을 선발할때 업무수행 능력이 아니라
    • 협력을 잘하는지,
    • 애매모호한 상황을 즐길수있는지,
    • 자신보다 지위가 높은 사람에게도 자신있게 의견을 말할수있는지를 봤다
  • 새로운 수술 방법을 도입할때 개개인이 새로운 기술을 획득하는것이라고 생각하지 않았고 함께 일하는 새로운 방법을 만들어야한다고 생각했다

 

다시 돌아와서,

PHP에서 자바로 성공적으로 전환한 팀의 특징

  • 리더와 팀원들이 학슴에 대한 태도가 달랐다
    • 같이 학습해야한다고 받아들임
    • 리더는 기회와 가능성, 큰 변화의 흐름에 동참하라는 중요성과 즐거움을 강조함
  • 실패한 팀은
    • 학습을 개개인의 과제로 돌렷음
    • 리더는 낙오의 위험성을 경고하고 팀원들의 실력이 부족하다 불평함

 

 

 

 

프로젝트 확률론

  • 당신은 프로젝트 매니저다
  • 당신에겐 7명의 팀원이 있다
  • 당신은 기가막히게 맡은 일감을 정확히 7등분했다
  • 각각의 일감은 독립적이라 담당자들은 자신의 일만 잘 하면 된다
  • 당신의 팀원들에게 질문한다 “일정안에 끝낼 수 있나요?”
  • 7명의 팀원들은 모두 똑같은 답변을 한다 “90% 확률로 끝낼수 있다”고
  • 그러면 이 프로젝트는 기간안에 끝날 수 있을까?
    • 흔히 범하는 실수는 이 프로젝트의 성공률이 90%라고 착각하는 것이다
    • 프로젝트가 기간안에 끝날 확률은 90%가 아니다
    • 0.9의 7승인 0.48, 즉 48%가 나온다

 

 

이러한 업무진행방식을 애자일하게 바꾼다면?

워드 커닝햄은 이렇게 말했다

  • 12가지 할일이 있고 12명의 개발자가 있다면
  • 1인 1일을 주는게 아니라
  • 12명에게 3가지 일을 준다
  • 3가지 일이 끝나면 다음 3가지 일을 준다
  • 왜냐?
    • 유연하게 협력을 하게되며
      • “관심사의 섞임”이 일어나게되고 정보를 빠르게 공유할 수 있게 된다
      • 빠른 정보 공유를 통해 학습도 빠르게 가능하고,
      • 병목지점이 발생하면 내가 도와줄 수 있게된다

 

 

애자일은 다음 성질이 있다

  • 좋은 일에 대해서는 “그리고” 확률을 “또는” 확률로 바꾸고
  • 나쁜 일에 대해서는 “또는” 확률을 “그리고” 확률로 바꾸는 성질

 

예시

  • 한 명이라도 좋은 통찰이 있었다면 공유를 해서 좋은 영향을 줄 수 있다(“또는” 확률)
  • 버그가 있더라도 모든사람이 버그를 발견하지 못해야만 구멍이 발생하도록 제한한다(“그리고” 확률)

 

 

 

 


애자일

애자일이란

  • 그래서 애자일이 뭔데?

 

애자일은,

  • 소프트웨어를 개발하는 여러 방법중에서 한 가지 방법임
  • 애자일 이전에는 계획주도 방식
  • 하지만 개발을 할 때 불확실성이 많이 있고, 계획주도 방식은 불확실성을 해결할 수 없다
  • 따라서 애자일 방법론은 불확실성에도 유연하게 대처하기위해
    • 다양한 사람으로부터
    • 짧은 주기로
    • 잦은 피드백을 받으며
    • 유연하게 개발하는 방법
  • 이런 애자일 방법을 실천하기 위해서는 위에서 설명한
    • 함께(협력) 자라기(학습)가 필요하다

 

 

 

애자일을 애자일스럽게 도입하기

  • 많은 조직들이 애자일을 도입하려고 하지만 노력에 비해 성공률이 높지 않다
  • 왜일까?
  • 애자일을 반(反)애자일적으로 진행하기때문
    • 애자일은 불확실성을 대처하는 방법론
    • 근데 애자일을 도입할때 확실성 위에서 진행하려고해서 문제가 발생한다
      • 애자일을 도입하려면 어떤것을 해야할지 명확하게 알려달라고한다
      • 하지만, 이것 자체가 애자일스럽지 않다

 

 

사실 이 사람도 애자일하게 가자는 말을 하고싶었던것은 아닐까 싶다

 

한국까지 조롱 이어지는 '펀쿨섹좌' 황당 발언들 | 중앙일보

동어반복, 논점이탈, 순환논법 등의 화법 때문에 그의 발언을 '시'라고 부르며 조롱하는 사람들이 많습니다.

www.joongang.co.kr

 

 

 


책의 한 줄 요약

  • 큰 성과를 내려면 함께 해야하며, 같이 매일 배워야 한다

 

 

디스크 읽기 방식

  • 데이터베이스 성능 튜닝은 디스크 IO를 어떻게 줄이느냐가 관건
  • 데이터베이스에서 병목지점은 항상 디스크 장치
    • 하드디스크
    • SSD → 하드디스크와 비교해서 용량이 적으며 비싸지만 더 사용된다 왜? 랜덤IO가 빨라서

 

순차IO와 랜덤IO

  • 디스크 헤더가 안움직이고 한번에 읽는다 → 순차IO
  • 헤더 이동없이 얼마나 많이 읽을 수 있는가 → 디스크의 성능
  • 순차IO가 랜덤IO보다 항상 성능이 좋다 (약 3배정도)(SSD의 경우도 그렇다)
  • so, 쿼리튜닝 == 랜덤IO를 줄인다

 

인덱스란?

  • DBMS가 데이터베이스 테이블의 모든 데이터를 검색해 원하는 결과를 가져오려면 시간이 오래 걸린다.
  • 그래서 컬럼들의 값과 해당 레코드가 저장된 주소를 키와 값의 쌍으로 삼아 인덱스를 만들어두는 것
  • DBMS의 인덱스는 컬럼의 값을 주어진 순서로 미리 정렬해서 보관한다.
  • 키밸류로 컬럼값과 레코드가 저장된 주소를 미리 저장해두는 자료구조
  • INSERT, UPDATE, DELETE 성능을 포기하고 읽기 속도에 몰빵하는 기능

 

인덱스 알고리즘

  • 비트리 알고리즘
  • 해쉬 인덱스 알고리즘

 

B-Tree 인덱스

  • 칼럼의 원래 값을 변형하지 않고 인덱스 구조체 내에서는 항상 정렬된 상태로 유지한다
  • 데이터베이스에서 인덱스와 실제 데이터가 저장된 데이터는 따로 관리되는데,
  • 인덱스의 리프 노드는 항상 실제 데이터 레코드를 찾아가기 위한 주솟값을 가지고 있다.

 

B-Tree는 왜 빠른가?

  • 어떠한 값에 대해서도 같은 시간에 결과를 얻을 수 있다
  • 리프노드를 선형 탐색한다면 71이라는 값을 찾기위해 O(n)
  • B-tree는 O(logN)

 

B+Tree

  • 리프노드끼리 LinkedList형태로 연결됨
  • 하나의 노드에 더 많은 데이터를 담기에 트리의 높이가 낮아짐
  • 리프노드에 모든 데이터가 있기에 풀스캔시 리프노드의 LinkedList를 한번만 선형탐색하면 된다

 

 

B-Tree 인덱스 사용에 영향을 미치는 요소

 

인덱스 키 값의 크기

  • 인덱스도 페이지 단위로 관리됨
  • 인덱스를 구성하는 키값의 크기가 커지면 디스크로부터 페이지를 읽는 횟수가 늘어난다 → 느려진다
    • 이노디비의 기본 페이지 크기는 16KB
    • 추가

 

비트리의 깊이

  • 깊이도 중요하지만 제어할 수 없다
  • 인덱스 키 값이 커지면 하나의 인덱스 페이지에 더 적은 수의 키 값이 저장되고, 비트리의 깊이가 깊어짐 → 더 많은 디스크 읽기

 

인덱스의 선택도(기수성)

  • 선택도(Selectivity) or 기수성(Cardinality)
  • 모든 인덱스 값 중에 유니크한 값의 수
    • 100개중에 유니크한게 10개라면 기수성은 10
  • 선택도가 높다면 검색 대상이 줄어들기에 빠르다
SELECT * FROM tb_city
WHERE country='KOREA' AND city='SEOUL';
  • 다음과 같은 조건
    • tb_city 테이블에는 1만건의 데이터
    • country 컬럼에만 인덱스
    • country와 city 컬럼은 중복없다
  • country 컬럼의 유니크 값이 10개일 때
    • country=’KOREA’ 라는 조건으로 인덱스를 검색하면 1만 건의 데이터 중 1,000건(10,000 / 10)의 데이터가 일치할 것이라 예상할 수 있다.
    • city=’SEOUL’인 레코드는 1건이므로 1,000건 중 999건이 불필요하게 읽히는 것으로 볼 수 있다.
  • country 컬럼의 유니크 값이 1,000개일 때
    • country=’KOREA’ 라는 조건으로 인덱스를 검색하면 1만 건의 데이터 중 10건(10,000 / 1,000)의 데이터가 일치할 것이라 예상할 수 있다.
    • city=’SEOUL’인 레코드는 1건이므로 10건 중 9건이 불필요하게 읽히는 것으로 볼 수 있다.

 

읽어야하는 레코드의 수

  • 인덱스로 읽어야하는 데이터가 전체 테이블 레코드의 20~25%를 넘어가면 보통 인덱스를 안쓰고 풀스캔
    • 예시로, 100만건중에 50만건을 읽는 쿼리가 있다면 인덱스 사용안하고 풀스캔

 

 

MySQL의 인덱스 사용방법

  • 인덱스 레인지 스캔
  • 인덱스 풀 스캔
  • 루스 인덱스 스캔 (Loose)
  • 인덱스 스킵 스캔

 

인덱스 레인지 스캔

  • 가장 대표적인 방식
  • 검색해야할 인덱스 범위가 결정됐을때 사용
  • 인덱스의 리프노드에서 검색 조건에 일치하는 건들은 데이터 파일에서 레코드를 읽어오는 과정이 필요하다
SELECT * FROM employees WHERE first.name BETWEEN 'Ebbe' AND 'Gad';

  • 두꺼운 화살표가 실제 스캔하는 범위이다
  • 루트노드 → 브랜치노드 → 리프노드를 거쳐 필요한 레코드의 시작점을 찾는다
  • 리프노드에서 Ebbe와 Gad를 찾았다면 그 사이를 스캔한다
  • 그 사이에 대해서는 실제 데이터 파일로 랜덤엑세스를 통해 가져오는 과정이 필요하다
  • 만약 커버링 인덱스가 적용됐다면 이 과정 없음
    • 쿼리를 충족시키는 데 필요한 모든 데이터를 갖고 있는 인덱스를 커버링 인덱스라고한다

커버링 인덱스

  • customer_id에만 인덱스가 있다고 했을때
select *
from temp_ad_offset
where customer_id = 7;

select customer_id
from temp_ad_offset
where customer_id = 7;

Extra 항목은 옵티마이저가 어떻게 동작하는지에 대해 알려주는 힌트 값

  • Using filesort: Orderby처리가 인덱스를 사용하지 못할때
  • Using index: 커버링 인덱스 사용할때
  • Using temporary: 쿼리의 중간결과를 위해 임시테이블을 생성했을때
  • Using index for skip scan: 인덱스 스킵 스캔 최적화를 한 경우

https://zzang9ha.tistory.com/436

 

MySQL EXPLAIN 실행계획 마스터하기(feat. RealMySQL 8.0)

💯 MySQL EXPLAIN 실행계획 마스터하기(feat. RealMySQL 8.0) 실행 계획(EXPLAIN) 이란? 대부분의 DBMS는 많은 데이터를 안전하고, 빠르게 저장 및 관리하는 것이 주목적이다. 이러한 목적을 달성하기 위해 사

zzang9ha.tistory.com

 

 

 

인덱스 풀 스캔

  • 인덱스의 처음부터 끝까지 모두 읽는 방식
  • 인덱스 전체 크기는 테이블의 전체크기보단 작기에 테이블 풀스캔보단 나은 비용
  • (A, B, C) 라는 인덱스가 있다
SELECT * FROM employees WHERE B = 'b' AND C = 'c';
  • 조건절에 사용된 컬럼이 A를 포함하지 않기에 풀스캔 발생

 

루스 인덱스 스캔

  • 듬성듬성 인덱스를 읽는 방식
  • 인덱스 레인지 스캔과 비슷하지만, 중간에 필요하지 않은 인덱스 키 값은 무시한다
  • 일반적으로 groupby나 max(), min() 함수에 대한 최적화로서 옵티마이저가 판단한다

 

인덱스 스킵 스캔

  • MySQL8.0부터 추가된 기능
  • 조건절에 첫번째 인덱스가 없어도 두번째 인덱스만으로 인덱스 사용하게해주는 기능
  • 바로 위 인덱스 풀 스캔의 쿼리가 인덱스를 타게된다
  • 단,
    • where절에 포함되지않은 인덱스 컬럼의 유니크한 개수가 적어야함(A컬럼의 선택도가 낮아야함)
    • 그렇지 않다면 인덱스에서 스캔해야 할 시작지점을 검색하는 작업이 많아지며 오히려 더 느려진다
    • 커버링 인덱스를 사용할 수 있는 경우에만 스킵스캔이 된다.

 

 

멀티밸류 인덱스

  • 다중컬럼 인덱스(복합인덱스)
  • 각 컬럼은 자기 바로 앞 컬럼에 의존하여 정렬돼있음
    • 두번째 컬럼은 첫번째 컬럼에 의존해 정렬돼있다
    • 세번째 컬럼은 두번째 컬럼에 의존해 정렬돼있다
  • 선택도가 높은 컬럼을 앞쪽으로
    • where절에서 자주 사용되는 조건을 앞쪽으로
    • join조건에서 자주 사용되는 조건을 앞쪽으로
    • orderby절에서 자주 사용되는 조건을 앞쪽으로

 

 

인덱스 스캔 방향

  • 인덱스를 생성할 때 설정한 규칙에 따라서 오름차순/내림차순으로 정렬되어 저장된다
  • 오름차순으로 저장되었다고 해서 오름차순으로만 이용할 수 있는건 아니다
    • 오름차순 인덱스를 거꾸로 읽으면 내림차순으로 정렬된 인덱스로도 활용 가능
    • 실행계획에서 결정됨
    • ORDER BY 처리나 MIN() 또는 MAX() 함수 등의 최적화가 필요한 경우 인덱스를 읽는 순서만 변경해서 인덱스 생성 시 지정한 정렬 규칙에 대한 문제점을 해결할 수 있다.

 

내림차순 인덱스는 느리다

  • 왜?
    • 페이지 잠금이 인덱스 정순 스캔에 적합한 구조이므로
    • 페이지 내에서 인덱스 레코드가 단방향으로만 연결된 구조이므로
  • 쿼리에서 자주 사용되는 정렬 순서대로 인덱스를 생성하는 것이 잠금 병목 현상을 줄이는 데 도움됨

 

 

B-tree 인덱스의 가용성과 효율성

  • where조건이나 groupby, orderby절이 어떤 경우에 인덱스를 사용하는지 알아야함

 

비교 조건의 종류와 효율성

SELECT * FROM dept_emp
WHERE dept_no= 'd002' AND emp_no >= 10114 ;
  • 1번: 인덱스가 (dept_no, emp_no)인 경우
  • 2번: 인덱스가 (emp_no, dept_no)인 경우

1번 케이스

  • dept_no가 ‘d002’이고 emp_no가 10114보다 큰 레코드를 찾는다.
  • 이후에는 dept_no가 ‘d002’가 아닐 때까지 인덱스를 쭉 읽기만 하면 된다.

2번 케이스

  • emp_no가 10114 보다 큰 레코드이고 dept_no가 ‘d002’인 레코드를 찾는다.
  • 이후 찾은 모든 레코드에 dept_no가 ‘d002’인지 비교하는 작업을 수행한다.

 

 

인덱스의 가용성

  • B-Tree 인덱스의 특징은 왼쪽 값에 기준해서 오른쪽 값이 정렬돼 있다는 것이다.
  • 하나의 칼럼으로 검색해도 값의 왼쪽 부분이 없으면 인덱스 레인지 스캔 방식의 검색이 불가능하다.
SELECT * FROM employees WHERE first_name LIKE '%mer1';
  • 이 쿼리는 인덱스를 못탄다
    • first_name 컬럼에 저장된 값의 왼쪽부터 비교해가며 일치하는 레코드를 찾아야 하는데,
    • 조건 값의 왼쪽 부분(’%mer1’)이 정해져 있지 않기 때문이다
SELECT * FROM dept_emp WHERE emp_no>=10144;
  • 인덱스가 (dep_no, emp_no)로 생성되어 있다면 아래의 쿼리는 인덱스를 효율적으로 사용하지 못한다
  • 다중 컬럼 인덱스로 생성된 인덱스이므로 dept_no를 먼저 정렬한 후, 다시 emp_no 컬럼값으로 정렬돼 있기 때문 (랜덤IO)

 

B-tree에서 인덱스를 효율적으로 사용하지 못하는 케이스

  • NOT-EQUAL로 비교된 경우 (NOT IN, NOT BETWEEN, IS NOT NULL)
    • WHERE column <> 'N'
    • WHERE column NOT IN (10,11,12)
    • WHERE column IS NOT NULL
  • LIKE %xxx 형태 문자열 패턴 비교인 경우
    • WHERE column LIKE '%test‘
    • WHERE column LIKE '%test%‘
    • WHERE column LIKE '_test‘
  • 스토어드 함수나 다른 연산자로 인덱스 컬럼이 변형된 후 비교된 경우
    • WHERE SUBSTRING(column,1, 1) = 'X'
    • WHERE DAYOFMONTH(column) = 1
  • 인덱스 컬럼의 타입을 변환해야 비교가 가능한 경우
    • WHERE char_column = 10 → char를 int와 비교
  • 문자열 데이터 타입의 콜레이션이 다른 경우
    • WHERE utf8_bin_char_column = euckr_bin_char_column

 

 

클러스터링 인덱스

  • pk가 비슷한 레코드끼리 묶어서 인덱스로 저장한 것
  • 클러스터링 인덱스의 리프노드에는 모든 레코드의 컬럼이 저장되어있다
  • 클러스터링이란
    • 여러개를 하나로 묶는다는 의미로 주로 사용됨
    • MySQL 서버에서 클러스터링은 테이블의 레코드를 비슷한 것을 기준으로 묶어서 저장하는 형태
    • 비슷한 것 = pk
    • pk설정시 그 컬럼은 자동으로 클러스터링 인덱스가 된다
    • 주로 비슷한 값을 동시에 조회하는 경우가 많다는 점에서 착안된 설계
    • 테이블의 레코드가 pk 기준으로 정렬되어 저장되는 경우를 → 클러스터링 인덱스 or 클러스터링 테이블
  • pk에 따라 레코드의 저장위치가 결정되므로 테이블의 레코드 저장 방식으로 볼 수 있다
    • 인덱스 자체의 리프노드가 곧 데이터다. → 테이블 자체가 인덱스다
      • 클러스터 인덱스는 페이지를 알기 때문에 바로 그 페이지를 펴는 것
      • 넌 클러스터 인덱스는 뒤에 목차에서 찾고자 하는 내용의 페이지를 찾고 그 페이지로 이동하는 것.
      • 테이블 스캔은 처음부터 한 장씩 넘기면서 내용을 찾는 것
  • pk가 없다면 다음 기준으로 이노디비 스토리지 엔진이 pk를 대체할 컬럼을 선정한다
    • pk가 있다면 pk를 클러스터링 키로 선택
    • not null인 유니크 인덱스중에 첫번째를 클러스터링 키로 선택
    • 자동으로 유니크한 값을 가지도록 증가되는 컬럼을 내부적으로 고른 후 클러스터링 키로 선택
  • 장점 (주로 빠른 읽기)
    • pk(클러스터링키)로 검색할때 성능이 매우 빠름(특히 pk를 범위검색에 사용하는 경우)
    • 테이블의 모든 세컨더리 인덱스가 pk를 가지고있기 때문에 인덱스만으로 쿼리를 처리할 수 있을 확률이 높음(커버링 인덱스)
  • 단점 (주로 느린 쓰기)
    • 테이블의 모든 세컨더리 인덱스가 pk를 가지고있기 때문에 클러스터링 키값이 클수록 전체적으로 인덱스의 크기가 커짐
    • 세컨더리 인덱스로 검색할때 pk로 한번 다시 검색해야하기에 처리성능이 느림
    • INSERT를 할 때 pk에 의해 레코드 저장 위치가 결정되기에 처리 성능이 느림
    • pk를 변경할 때 레코드를 DELETE하고 INSERT해야하기에 처리성능이 느림

  • 클러스터링 인덱스는 인덱스에 실제 데이터를 저장하고있음
  • 논 클러스터링(세컨더리) 인덱스는 인덱스 페이지를 별도로 관리함
    • 논 클러스터링 인덱스의 장단점
      • 장점
        • 실제 데이터 페이지는 정렬되지 않기에 INSERT, UPDATE, DELETE 성능 좋음
      • 단점
        • 인덱스만 정렬되고 실제 데이터는 정렬되지 않기에 클러스터링 인덱스에 비해 검색 느림

 

논 클러스터링 인덱스(세컨더리 인덱스)

  • 클러스터링 인덱스(PK 인덱스)를 제외한 모든 인덱스
  • 리프 노드에서 레코드의 물리적인 주소값이 아닌 PK를 가지기 때문에 레코드를 접근할 때 바로 접근할 수 없다
  • 왜 논 클러스터링 인덱스를 통한 검색은 클러스터링 인덱스를 한번 거치게 했을까?
    • 레코드 변경시 인덱스의 부하를 줄이기 위함
    • pk가 변경되면 레코드의 물리적 주소가 바뀜
    • 논 클러스터링 인덱스는 실제 레코드 주소값(pk)이 아닌 논리적인 pk만 참조하기에 레코드의 값이 변경되어도 논 클러스터링 인덱스는 바뀌지 않는다

클러스터링 인덱스 → pk(데이터)

논 클러스터링 인덱스 → 클러스터링 인덱스 → pk(데이터)

 

  • 클러스터링 인덱스: 인덱스를 가지고 리프노드까지 탐색해서 원하는 데이터를 바로 얻음
  • 논 클러스터링 인덱스: 인덱스를 가지고 리프노드에 탐색해서 실제 데이터 위치를 얻음 → 실제 데이터는 힙영역에서 얻는다

 

클러스터링 테이블 사용시 주의사항

  • 이노디비 테이블(클러스터링 테이블)에서는 주의할 것이 있다
  • 모든 논 클러스터링(세컨더리) 인덱스가 pk를 포함한다
  • 그래서 pk의 크기가 커지면 세컨더리 인덱스도 커진다
  • 그래서 다음과 같은 주의사항들이 있다
    • pk는 auto_increment 보다는 업무적인 컬럼으로 생성
      • 이노디비에서 pk는 클러스터링 키로 사용되며, 이 값에 따라서 레코드의 위치가 결정됨
      • 즉, pk로 검색하는 경우 클러스터링 되지 않은 테이블에 비해서 매우 빠르다는 뜻
      • 따라서 검색에서 빈번하게 사용되고 → 업무적으로 pk가 해당 레코드를 대표할 수 있다면 pk로 설정하는 것이 좋다
    • pk는 반드시 명시할 것
      • 명시하지 않으면 이노디비 스토리지 엔진이 내부적으로 일련번호 컬럼을 추가한다
      • 하지만 이 컬럼은 보이지 않기에 사용자가 접근할 수 없다
      • 따라서 명시하지 않아도 일련번호 컬럼이 추가되기에 명시하는거나 다름없다(오히려 접근이 안되기에 사용불가라는 단점만 있음)
    • auto_increment 컬럼을 인조 식별자로 사용할 경우
      • 세컨더리 인덱스도 필요하고 프라이머리 키의 크기도 길다면 AUTO-INCREMENT 칼럼을 추가하고 이를 프라이머리 키로 설정하면 된다.
      • 이를 인조 식별자라고 함

 

 

유니크 인덱스

  • 같은 값이 2개 이상 저장될 수 없음을 의미
  • 인덱스라기보단 제약조건에 가깝다 → 하지만 인덱스 없이 유니크 제약만 설정할 방법이 없다
  • 유니크 인덱스가 걸린 컬럼에 null도 저장될 수 있지만 null은 중복 허용임
  • 유니크 인덱스가 다른 세컨더리 인덱스보다 조회가 빠른가?
    • 그렇긴한데 유니크”인덱스”라서 빠른건 아니다
    • 인덱스의 성격이 유니크한지 아닌지의 차이이지 인덱스 자체가 동작하는 방식은 동일하다
      • 유니크하지 않은 세컨더리 인덱스는 읽어야 할 값이 많아서 느린것
      • 유니크 인덱스는 1개뿐이라서 빠른것 (1개뿐임이 보장되기에 실행계획이 다름)
      • 인덱스 자체에 대한 차이는 아님
  • 주의
    • 유니크 인덱스는 세컨더리 인덱스보다 변경에 느림
    • 일반인덱스와 유니크인덱스는 인덱스 자체로는 동일하다
    • pk를 유니크 인덱스로 쓰지말자 중복이다

 

 

참고:

 

'DB' 카테고리의 다른 글

[Typeorm] save() 알차게 사용하기  (1) 2023.04.01
[DB] 데이터베이스 정규화  (0) 2021.07.14

객체지향에 대해 설명해주세요

  • 객체란? -> 현실에 존재하는 대상
  • 프로그래밍에서 필요한 데이터를 추상화시켜 상태행위를 가진 객체를 만들고
  • 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법론

 

객체지향의 장단점이 뭐죠?

  • 장점은
    • 코드 재사용성이 좋다. 상속을 통한 확장도 가능
    • 유지보수가 쉽다. 절차지향에서는 일일이 찾아서 수정해야하지만, 객체지향에서는 클래스 내부를 보면 된다
    • 대형 프로젝트에 적합하다. 클래스단위로 모듈화 가능이기에 협업에 용이
  • 단점은
    • 개발속도가 상대적으로 느리다
    • 설계하기 쉽지 않다

 

클래스와 인스턴스가 뭐죠?

  • 클래스는
    • 대상의 속성과 행위를 변수와 메서드로 정의한 것
  • 인스턴스는
    • 정의한 클래스를 실제 메모리에 할당시키는 것

 

객체지향의 특성은 뭐가있죠?

  • 캡슐화
    • 클래스라는 캡슐에 속성과 행위를 묶고, 외부로부터 보호하는 것
      • 데이터 보호
      • 데이터 은닉 -> 필요한 부분만 노출
    • 접근제어자
    • 게터, 세터 -> 결합도를 낮출 수 있다
  • 상속
    • 기존 클래스를 재활용하여 새로운 클래스를 만드는 것
    • 속성과 행위를 물려받음
    • 중복을 제거하고 필요한 부분만 수정할 수 있다
  • 추상화
    • 객체지향 관점에서 클래스를 정의하는 것
    • 객체의 본질적이고 공통적인 부분만 추출하여 정의하는 것
      • 추상클래스
      • 인터페이스
  • 다형성
    • 객체의 속성이나 행위가 상황에 따라 여러가지 형태를 가질 수 있는 것
    • 상위클래스의 참조변수가 하위클래스 객체를 참조하는 것
      • 오버로딩
      • 오버라이딩
        • 오버로딩 오버라이딩처럼 메서드가 상황에따라 다르게 동작할 수 있고
      • 아래 사진처럼 상위클래스 변수가 하위클래스 변수를 받을 수 있는것
      • 이것이 다형성

 

 

 

참고:

https://www.codestates.com/blog/content/%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%ED%8A%B9%EC%A7%95

 

객체 지향 프로그래밍의 4가지 특징ㅣ추상화, 상속, 다형성, 캡슐화 -

객체 지향 프로그래밍은 객체의 유기적인 협력과 결합으로 파악하고자 하는 컴퓨터 프로그래밍의 패러다임을 의미합니다. 객체 지향 프로그래밍의 기본적인 개념과 그 설계를 바르게 하기 위

www.codestates.com

 

정말 오오오오오랜만에 글을쓴다

다시 잘 써보자고


가비지란?

  • JVM의 힙영역에 할당됐던 메모리중 필요없게 된 메모리를 가비지라고 한다
  • C언어의 경우 free() 함수를 통해 직접 메모리 해제
  • 자바는 gc가 해준다
Person person = new Person();
person.setName("lsh");
person = null;

// 가비지 발생
person = new Person();
person.setName("ksh");
 

가비지 컬렉션 장점

  • 개발자가 완벽하게 신경쓰지 않아도 된다

가비지 컬렉션 단점

  • 언제 메모리가 해제될지 개발자가 알 수 없다
  • GC 동작중에는 STW, 오버헤드 발생

 

 

GC란

  • 힙 영역에서 유효하지 않은(사용하지 않는) 메모리를 자동으로 수거하는 기능
  • 힙 영역은 다음 두가지가 전제가 된다
    • 대부분의 객체는 금방 unreachable 상태가 된다
    • 오래된 객체 -> 새로운 객체로의 참조는 아주 적다
  • 따라서 힙 영역은 객체의 생존 기간에 따라 Young 영역과 Old 영역으로 나눔

young영역

  1. young은 eden과 survivor1, 2로 구성
    1. eden
      1. eden은 new를 통해 새로 생성된 객체가 위치함
      2. 정기적인 gc 수행 후 살아남은 객체들은 survivor1,2로 넘김
    2. survivor
      1. 최소 1번 이상의 gc에서 살아남은 객체가 위치한 영역
      2. survivor1이나 survivor2중 하나는 꼭 비어있어야 한다
  2. 이곳에서의 gc 동작을 Minor gc라고함

 

old영역

  • young영역에서 reachable 상태를 유지하여 살아남은 객체가 복사되어 이곳에 위치하게된다
  • 이곳에서의 gc를 메이저gc 혹은 full gc라고함

  • card table
    • 예외적으로 old영역에 있는 객체가 Young영역에 있는 객체를 참조하는 경우도 있다
    • 이럴때를 대비하여 512바이트의 덩어리(청크)로 되어있는 카드테이블이라는 것이 있다
    • 마이너 gc가 발생할때 old영역에서 참조하는 young으로 참조하는 객체가 있는지 old영역을 확인안해도 되기에 효율적

 

왜 굳이 영역을 나누는가?

  • heap 영역을 나누는 이유는 heap 전체를 탐색하여 메모리를 해제하는 full gc로 인한 성능상의 이슈를 최소화 시키기 위함
    • weak generational hypothesis의 장점을 극대화 시키기 위함
    • 주로 old 영역의 객체는 크기가 큰 것들이 대부분이고 gc 소요시간이 Minor gc보다 오래걸린다
      • Minor gc와 Major gc의 비율간의 트레이드 오프
  • survivor 영역을 두개로 나누는 이유는 메모리 단편화 문제를 해결하기 위함

내부단편화

 

외부단편화

 

 

 

GC 동작 방식

  • young 영역과 old 영역의 세부적인 동작방식은 다르나 다음 두가지는 공통이다
    • Stop the world
      • gc 실행을 위해 jvm이 애플리케이션의 실행을 멈추는 작업
      • gc를 실행하는 쓰레드를 제외한 모든 스레드가 중단됨
      • gc튜닝은 대부분 이 시간을 줄이는것
    • Mark and sweep
      • 마크 -> 사용되는 메모리와 그렇지 않은 메모리를 식별하는 작업
      • 스윕 -> 마크단계에서 사용되지 않는것으로 판별된 메모리를 해제하는 작업
      • 컴팩션 -> 파편화된 메모리 영역을 앞에서부터 채워나가는 작업

 

Minor GC 동작 방식

사진출처: https://inpa.tistory.com/entry/JAVA-%E2%98%95-%EA%B0%80%EB%B9%84%EC%A7%80-%EC%BB%AC%EB%A0%89%EC%85%98GC-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%F0%9F%92%AF-%EC%B4%9D%EC%A0%95%EB%A6%AC

 

☕ 가비지 컬렉션 동작 원리 & GC 종류 💯 총정리

Garbage Collection(GC) 이란? 가비지 컬렉션(Garbage Collection, 이하 GC)은 자바의 메모리 관리 방법 중의 하나로 JVM(자바 가상 머신)의 Heap 영역에서 동적으로 할당했던 메모리 중 필요 없게 된 메모리 객

inpa.tistory.com

 

 

age란?

  • Survivor 영역에서 객체가 gc로부터 살아남은 횟수
  • 임계점에 다다르면 Promotion되어 old영역으로 이동한다
  • JVM중 일반적인 HotSpot JVM의 경우 age 임계값이 31이다
 

 

 

 

Major GC 동작 방식

  • young에서 age가 차서 넘어온 객체들
  • old 영역의 메모리가 부족해지면 major gc 수행
  • old 영역에서 한번에 삭제함
  • old 영역은 young 영역보다 상대적으로 큰 공간을 가지고있기에 gc 수행시간 길다 → STW
  • STW를 줄이기위해 여러 가비지 컬렉션 알고리즘이 존재

Minor Major GC 비교

  • 만약 gc가 동작해도 모든 객체가 reachable해서 삭제될 객체가 없다면? → OOM 발생

 

 

 

GC 알고리즘

Serial GC

  1. 1 core cpu일때 사용하기위함
  2. Gc를 처리하는 스레드가 1개라서 STW시간이 제일 길다
  3. 실무에서 사용하는 케이스가 거의 없다고한다

 

Parallel GC

  • 자바8의 default gc
  • Minor gc를 멀티스레드로 수행함 (Major gc는 여전히 싱글스레드)
  • Serial gc에 비해선 STW 감소
  • 스레드는 기본적으로 cpu 개수만큼 할당됨

 

Parallel old GC

  • Parallel gc를 개선함
  • old영역에서도 멀티스레드로 메이저 gc수행
  • Mark - summary - compact 방식

 

Cms GC

  • 어플리케이션의 쓰레드와 GC 쓰레드가 동시에 실행되어 stop-the-world 시간을 최대한 줄이기 위해 고안된 GC
  • 단, GC 과정이 매우 복잡해짐.
  • GC 대상을 파악하는 과정이 복잡한 여러단계로 수행되기 때문에 다른 GC 대비 CPU 사용량이 높다
  • 메모리 파편화 문제
  • CMS GC는 Java9 버전부터 deprecated 되었고 결국 Java14에서는 사용이 중지

 

G1GC

  • Java 9 이상부터 default GC
  • 기존의 GC 알고리즘에서는 Heap 영역을 물리적으로 고정된 Young / Old 영역으로 나누어 사용하였지만, G1 gc는 아예 이러한 개념을 뒤엎는 Region이라는 개념을 새로 도입하여 사용.
  • 전체 Heap 영역을 Region이라는 영역으로 체스같이 분할하여 상황에 따라 Eden, Survivor, Old 등 역할을 고정이 아닌 동적으로 부여
  • Garbage로 가득찬 영역을 빠르게 회수하여 빈 공간을 확보하므로, 결국 GC 빈도가 줄어드는 효과를 얻게 되는 원리
    • 이전의 GC들처럼 일일히 메모리를 탐색해 객체들을 제거하지 않는다
    • 대신 메모리가 많이 차있는 영역(region)을 인식하는 기능을 통해 메모리가 많이 차있는 영역을 우선적으로 GC 한다. → 영역(region)을 나눠 탐색하고 영역(region)별로 GC가 일어난다.
    • 또한 이전의 GC 들은 Young Generation에 있는 객체들이 GC가 돌때마다 살아남으면 Eden → Survivor0 → Survivor1으로 순차적으로 이동했지만, G1 GC에서는 순차적으로 이동하지는 않는다. 
    • 대신 G1 GC는 더욱 효율적이라고 생각하는 위치로 객체를 Reallocate(재할당) 시킨다. 
    • 예를 들어 Survivor1 영역에 있는 객체가 Eden 영역으로 할당하는 것이 더 효율적이라고 판단될 경우 Eden 영역으로 이동시킨다.

 

ZGC

  1. Java 15에 release됨
  2. 대량의 메모리(8MB ~ 16TB)를 low-latency로 잘 처리하기 위해 디자인 된 GC
  3. G1의 Region 처럼,  ZGC는 ZPage라는 영역을 사용하며, G1의 Region은 크기가 고정인데 비해, ZPage는 2mb 배수로 동적으로 운영됨. (큰 객체가 들어오면 2^ 로 영역을 구성해서 처리)
  4. ZGC가 내세우는 최대 장점 중 하나는 힙 크기가 증가하더도 STW의 시간이 절대 10ms를 넘지 않는다는 것

참고: GC 성능 비교

 

 

G1GC

  • G1은 Garbage First 라는 뜻
  • 조기 승격(Promotion)에 덜 취약하다. → old로 너무 빠르게 이동되는 문제 → STW
  • 대용량 heap에서 확장성(특히 중단시간)이 우수하다.
  • full STW GC를 없애거나 확 줄일 수 있다.
  • Java 9 부터 default GC
  • RSet(Remembered Set)을 통해 어떤 객체가 어떤 리전에 저장되어있는지 추적 가능 → 전체 힙을 뒤질필요가 없어짐

 

G1GC 동작 과정

  1. Initial Mark - SWT : Old 영역에서 존재하는 객체들이 참조하는 Survivor 영역을 찾는다. SWT가 발생한다.
  2. Root Region Scanning : Initial Mark 단계에서 식별한 Survivor 영역에서 Old 영역을 가리키는 레퍼런스를 식별한다.
  3. Concurrent Mark : 힙 전체에 걸쳐 접근 가능한 살아있는 객체를 찾는다.
  4. Remark - STW : Concurrent Mark 단계를 검증하고, 최종적으로 살아남을 객체들을 식별한다. 이 단계에서는 SATB(Snapshot-At-The-Beginning) 알고리즘이 사용된다. STW가 발생한다.
  5. Cleanup - STW : 어플리케이션을 멈추고(STW) 살아있는 객체가 가장 적은 리전에 대한 미사용 객체를 제거한다. 이후 STW를 끝내고, 앞서 GC 과정에서 완전히 비워진 리전을 FreeList에 추가하여 재사용할 수 있게 한다.
  6. Copy : GC 대상 리전이었지만 Cleanup 과정에서 완전히 비워지지 않은 리전의 살아남은 객체들을 새로운 리전에 복사하여 Compaction 작업을 수행한다.

 

gc튜닝

  • 언제 튜닝해야하는가? → 성능저하의 원인이 명백히 gc때문일때
  • 튜닝의 핵심은
    • old영역으로 넘어가는 객체 최소화하기
    • Major gc 시간 짧게 유지하기

즉, Major gc를 적게발생시키고, 발생했다면 빠르게 끝내야함

 

GC튜닝 방법

  • 힙 크기 설정
    • 힙이 크면 gc수행시간이 늘어남, 힙이 작으면 gc가 더 자주 수행됨 -> 잘 조절해야함
  • Young영역과 Old영역 크기 비율 + Eden과 Survivor의 크기 비율
    • old영역이 커지면 → Major gc가 자주발생하지않음 하지만 발생하면 오래걸림

 

 

 

G1GC 튜닝포인트

G1GC가 제공하는 파라미터가 많기에 튜닝 포인트도 많다

  • Maximum GC Pause Time
    • -XX:MaxGCPauseMillis 설정을 통해 GC 실행 중에 최대 일시 중지 시간을 지정함으로써 높은 지연 시간을 최소화 하거나 높은 처리량을 설정할 수 있다.

 

  • Young Gen 사이즈 세팅을 하지 말 것(-XX:MaxGcPauseMillis 설정을 할 경우)
    • -Xmn(new 영역)이나 -XX:NewRatio 설정을 피해야 한다.
    • G1GC 알고리즘은 일시 중지 목표 시간을 충족하기 위해 Young 영역을 임의로 수정하게 되는데 Young 영역을 명시적으로 설정할 경우 일시 중지 목표 설정이 정상적으로 작동하지 않는다.

 

  • 다른 GC 알고리즘에서 사용하던 JVM 인수 제거
    • 기본적으로 G1GC의 경우 다른 GC 알고리즘(Serial, Parallel, CMS)에서 사용하던 JVM 인수와 같이 사용할 경우 G1GC의 파라미터가 정상적으로 동작하지 않을 수 있다.

 

  • 문자열 중복 제거
    • -XX:+UseStringDeduplication 설정을 통해 문자열 중복을 제거 한다.
    • JDK 개발팀의 조사에 따르면 다음과 같은 자바 애플리케이션의 특징이 있다고 한다
      • 프로세스의 25%는 문자열임
      • 그 중 13.5%는 중복 문자열임
      • 평균 문자열의 길이는 45자임
    • 예를들어 멤버리스트 조회시 status가 “ACTIVE”라는 동일한 문자열이나 다 다른 메모리 공간 점유

 

그 외의 주요 파라미터

 

 

 

GC 튜닝보다 메모리 누수 예방이 우선

  • 메모리 누수 : 사용되지 않는 객체들이 힙영역에 남아있는것

Static 변수에 의한 누수

  • Static 변수는 클래스가 로드될때 생성되어 JVM이 종료될때까지 메서드 영역에 남아있는다 (사용 여부와 관계x)
  • Static 변수가 객체를 참조 중이라면 해당 객체는 GC의 대상이 되지 않는다
  • 더 이상 사용하지 않는다면 null을 할당하여 참조를 제거하자

 

무분별한 Autoboxing

public class Adder {
       public long addIncremental(long l)
       {
              Long sum = 0L;
              sum = sum + l;
              return sum;
       }
       public static void main(String[] args) {
              Adder adder = new Adder();
              for(long i ; i < 1000 ; i++) {
                adder.addIncremental(i);
              }
       }
}

 

 

컬렉션 클래스의 데이터를 해제하지 않는 경우

  • List, Map, Set 같은 컬렉션 클래스들에 객체가 담겨있는 경우 객체의 참조가 해제되지 않음
  • null 참조로 해제한다
      public Object pop() {
        if (size == 0)
            throw new EmptyStackException();
        Object result = elements[--size];
        elements[size] = null; // 다 쓴 객체 참조 해제
        return result;
    }
  • Weak reference를 사용한다
    • 특정 key 값이 더 이상 사용되지 않는다고 판단되면 해당 Key - Value 쌍을 삭제
  • 자바에서 참조 종류는 다음 4가지가 있다
    • 강한 참조(Strong Reference)
      • 강한 참조는 Java의 기본 참조 유형으로 new 할당 후 새로운 객체를 만들어 해당객체를 참조하는 방식
      • 강함 참조를 통해 참조되고 있는 객체는 참조가 해제되지 않는 이상 가비지 컬렉션의 대상에서 제외된다.
Object obj = new Object();
// 만약 GC 를 원한다면 명시적으로 null 표시를 해줘야 한다.
obj = null;
  • 약한 참조(Weak Reference)
    • 약한 참조는 java의 lang 패키지의 WeakReference 클래스를 사용하여 생성한다.
    • 약한 참조는 GC가 발생하면 무조건 수거된다.
    • WeakReference가 사라지는 시점이 GC의 실행 주기와 일치한다.
Object obj = new Object();
WeakReference<Object> weakRef = new WeakReference<>(obj);
obj = null;

System.gc();

// 무조건 null 을 확인하게 된다.
System.out.println(weakRef.get());
  • Soft Reference
    • Soft 참조는 강한 참조와 약한 참조와는 다르게 GC에 의해 수거될 수도 있고, 수거되지 않을 수도 있다.
    • 메모리에 충분한 여유가 있다면 GC가 수행된다 하더라도 수거되지 않는다. 하지만 메모리가 부족하면 수거될 확률이 높다.
Object obj = new Object();
SoftReference<Object> softRef = new SoftReference<>(obj);
obj = null;

System.gc();

// GC 가 여유롭다면 해시코드를 확인할 수 있다.
System.out.println(softRef.get());
  • Phantom Reference?
    • 가장 약한 참조 유형입니다.
    • 객체 수거시에도 참조가 남아있는 참조 유형입니다.
    • 객체의 finalize() 메서드가 호출된 직후에 GC 에 의해 수거됩니다.
    • java.lang.ref PhantomReference class 로 만들 수 있습니다.
    • 생성자에는 넣고자 하는 클래스와 함께 ReferenceQueue 를 인자로 받습니다.
    • PhantomReference 는 객체가 참조되지 않습니다.
    • 객체의 finalize 메서드가 호출된 직후 Phantom Reference 가 ReferenceQueue 에 등록됩니다.
    • 이를 통해 객체의 finalize() 메서드가 호출되었음을 알 수 있습니다.
    • 일반적으로 Phantom Reference 는 Native 객체나 Direct Memory 와 같이 JVM 에서 관리되지 않는 자원들을 해제하기 위해 사용됩니다.

 

CustomKey 사용으로 인한 누수

  • Map을 사용할 때 custom key를 사용할 때는 equals()와 hashcode()를 값을 기반으로 구현해야한다
  • 아래의 경우 Key값이 같은 객체로 인식하지 못해서 계속 Map에 쌓이게 되면서 메모리를 점유하게 된다
public class CustomKey {
    private String name;
    
    public CustomKey(String name) {
        this.name=name;
    }
    
    public staticvoid main(String[] args) {
        Map<CustomKey,String> map = new HashMap<CustomKey,String>();
        map.put(new CustomKey("Shamik"), "Shamik Mitra");
   }
}

 

 

해제되지 않은 리소스로 인한 누수

  • close()나 try with resources 구문으로 리소스 반환해야함
public class Main {
    public static void main(String[] args) {
        try (FileWriter file = new FileWriter("data.txt")) { // 파일을 열고 모두 사용되면 자동으로 닫아준다
            file.write("Hello World");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

프로토콜

  • 통신에 참여하는 주체간에 데이터를 주고받는 과정을 정의한 규칙
  • 효율성, 호환성을 위해 정해놓은 규칙으로, 다수의 벤더와 관련 제품군 등장 및 이용 가능

 

 

 


OSI 7계층과 TCP/IP 프로토콜

두 모델의 공통점

  • 두 호스트 사이에서 이루어지는 네트워킹을 계층구조로 나눈것임
  • 각 계층에서 일어나는 일들을 모듈화 가능

 

두 모델의 차이점

  • OSI의 7,6,5층을 TCPIP에서는 한 층으로 퉁침
  • 이 측면에서는 OSI가 문제해결과 성능개선이 더 좋음

https://velog.io/@sj_dev_js/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-OSI-7%EA%B3%84%EC%B8%B5%EC%9D%84-%EC%99%9C-%EB%B0%B0%EC%9A%B8%EA%B9%8C

 

[네트워크] OSI 7계층을 왜 배울까?

네트워크를 공부할 때 가장 먼저 배우게 되는 것이 TCP/IP 모델 혹은 OSI 모델이다.오늘날의 네트워크에서 OSI모델은 참조적 모델일 뿐이고 실제로 쓰이는 것은 TCP/IP 모델이라는데 그렇다면 OSI 모

velog.io

 

 


1계층 : 물리계층

 

 

  • 상위계층(2계층)에서 받은 비트 스트림을 상대방의 물리계층으로 보내는 기능
  • 단지 데이터만 전달함
  • 전송단위(PDU)는 비트
  • 프로토콜: Modem, Cable, Fiber, RS-232C
  • 장비: 통신 케이블, 허브(리피터)

 

리피터란?

  • 전선(케이블)이 길수록 전기신호가 약해지는데 이를 증폭해줌
  • 지금은 네트워크 장비에 기본적으로 리피터기능이 탑재돼있기에 따로 리피터를 사용하지 않는다고함

허브란?

  • 컴퓨터 신호를 여러개의 다른 선으로 분산시키는 장치를 총칭함
  • 리피터는 1대1 연결만 가능
  • 허브는 다대다로 연결 가능
  • 얘도 리피터와 마찬가지로 전기신호의 증폭을 위해 사용
  • CSMA/CD 방식을 적용하기에 여러 장비에서 동시에 데이터를 전송하지는 못함 (A장비에서 데이터 전송중일때 B도 전송하면 충돌발생)
  • 특정 포트로만 데이터를 전송할수없고 모든 포트에 데이터를 전송하게 되기에 과도한 트래픽, 충돌 발생 -> 스위칭 허브 사용(레이어2에서 사용)

이렇게 생김

 

 


2계층 : 데이터링크 계층

 

  • 네트워크 기기들 사이에서 데이터를 전송하는 역할
  • 프레임이라는 단위
  • 3계층에서 내려준 패킷을 받아 헤더와 테일에 각각 주소와 제어정보를 추가함
  • 1계층을 통해 송수신되는 데이터의 전송 오류를 감지하여 재전송도 해줌
  • 맥주소를 가지고 통신
  • 맥주소란 컴퓨터의 물리적인 주소
  • ip주소가 시작점과 끝점의 주소라면 맥주소는 중간중간지점들의 주소
  • ex) 서울에서 부산으로 편지를 보낸다면 ip주소는 서울, 부산이 되고 맥주소는 서울우체국, 부산우체국1 등등이 된다
  • 프로토콜 : 이더넷, MAC, PPP, ATM, LAN, Wifi
  • 장비: 브릿지, 스위치

 

브릿지란?

  • 네트워크 세그먼트를 연결해주는 장치
  • 스위치가 나오기 전까지 브릿지가 주로 사용됐다고 함
  • LAN과 LAN을 연결하거나 컴퓨터 그룹(세그먼트)를 연결해주는 기능
  • 브릿지의 다섯가지 기능
    • Learning : A라는 호스트가 데이터를 주면 A의 맥주소를 브릿지의 맥주소 테이블에 저장
    • Flooding : 목적지 정보가 맥주소 테이블에 없다면 모든 포트로 데이터 전파
    • Forwarding : 목적지 정보가 맥주소 테이블에 있다면 해당 포트로 전송, 없다면 플로딩
    • Filtering : 브릿지를 건너지 못하게 막는 기능
    • Aging : 맥주소 테이블 데이터를 자동으로 삭제하는 일종의 TTL

 

스위치란?

  • 브릿지랑 비슷
  • 브릿지와의 차이는 -> 스위치는 하드웨어, 브릿지는 소프트웨어 방식이기에 스위치가 속도가 더 빠르다
  • 브릿지보다 포트수 많음, 포트별 속도지정이 가능
  • 여러모로 브릿지의 상위호환이기에 브릿지대신 스위치 사용한다
  • 스위치의 종류
    • L2스위치 : 기본적인 스위치. 데이터링크 계층에서 사용, 맥주소 기반으로 패킷 전달, 가격저렴
    • L3스위치 : L2스위치에 라우팅 기능이 추가됨, IP 정보를 보고 스위칭한다, 기능적으로 라우터와 똑같지만 라우터는 소프트웨어방식이기에 하드웨어 방식인 L3스위치가 더 빠르고 저렴
    • L4스위치 : 4계층 프로토콜인 TCP/UDP를 사용, IP와 포트 기반으로 스위칭, L4스위치에는 로드밸런싱 기능이 있음
    • L7스위치 : L4스위치와 기능,역할이 동일하나, L7스위치에서는 페이로드를 분석하여 패킷 처리. 페이로드를 분석함으로서 Dos, SYN Attack등 네트워크 공격 방어 가능. 가격 비쌈

 

 


3계층 : 네트워크 계층

  • 데이터그램이 가능 경로를 설정해줌
  • 데이터그램이란 네트워킹에서 데이터 전송의 단위, 그냥 데이터로 이해하면 될듯?
  • 라우팅 알고리즘을 통해 최적의 경로를 선택
  • 데이터를 목적지까지 안전하고 빠르게 전달하는게 중요 -> 이거를 라우팅이라고 한다
  • 전송단위 : 패킷
  • 프로토콜 : IP, ICMP
  • 장비 : 라우터, L3스위치

 

라우터란?

  • 네트워크에서 데이터 전송의 최적 경로를 찾아서 전송해주는 장비
  • L3와 기능 비슷, 하지만 소프트웨어 방식이기에 더 비싸고 느리고 초기설정 어려움
  • 라우터의 종류
    • 코어라우터, 센터라우터, 엣지라우터, 브로드밴드라우터, 핫스팟라우터, ISP라우터

 

 

 


4계층 : 전송계층

 

  • 발신지 - 목적지간 제어와 에러 관리
  • 패킷의 전송이 유효한지 확인하고 재전송을 하는 등 신뢰성있는 통신 보장
  • 오류검츨, 흐름제어, 패킷 생성, 전송, 재전송
  • 단위 : 세그먼트
  • 프로토콜 : TCP, UDP, ARP, RTR
    • 대부분 TCP
    • ACK을 통해 신뢰성있는 전송
    • UDP는 비연결성, 비신뢰성임. 수신자가 잘 받든말든 일단 데이터보냄, 에러나면 어플리케이션에서 알아서 처리해야함, 하지만 빠름, 실시간 서비스에서 적절
  • 장비: 게이트웨이, L4스위치

 

 

 


5계층 : 세션계층

  • 통신장치간의 상호작용을 설정, 유지, 동기화
  • 동시 송수신, 반이중, 전이중
  • 네트워크상 양쪽 연결을 관리하고 연결을 지속시켜줌
  • TCP/IP 세션을 만들고 없애는 역할

 

 


6계층 : 표현계층

 

  • 송신, 수신측 사이에서 데이터 형식을 정해줌(jpg, png등)
  • 7계층으로부터 받거나 주는 데이터의 인코딩, 디코딩이 이루어지는 계층
  • 프로토콜 : JPG, MPEG, SMB 등

 

 


7계층 : 응용계층

  • 사용자와 상호작용
  • 응용 SW
  • 프로토콜 : HTTP, DNS, Telnet, FTP등

 

 

 

 

 

참고:

https://youtu.be/8kI5OIrfZtI?si=-gZMcolC217Aht7y

https://backendcode.tistory.com/167

 

[네트워크] OSI 7 계층 (OSI 7 Layer)

이번에는 네트워크의 기본인 OSI 7 계층에 대해 정리할 것이다. 이번 글에서는 OSI 7 계층에 대해 다루고, 다음 글에서는 TCP/IP 4 계층에 대해 다루기 때문에 이어서 보면 이해하기 쉽다. 🖥️ 목차

backendcode.tistory.com

https://heisyoung.tistory.com/52

 

OSI 7계층 장비(리피터, 허브, 브리지, 스위치, 라우터)

1계층(물리 계층) - 리피터, 허브 리피터(Repeater) 긴 케이블일수록 신호가 약해지기 때문에 신호를 멀기 보내기 위한 증폭 장치이다. 지금은 다른 네트워크 장비에 기본적으로 리피터 기능이 탑재

heisyoung.tistory.com

 

 

 

 

메모

더보기

계층형 모델 (OSI 7Layer)

- 통신 장비들끼리 호환되도록 표준을 만든것

- 데이터가 전달되기위한 과정을 계층화 (ISO, DoD)

- 7단계중 한 곳에 이상이 생기면 다른 단계의 장비나 소프트웨어를 건들지 않아도 고칠 수 있다

- 복잡도를 줄이고 모듈화를 통한 기술발전, 호환성, 상호독립성

- 이 규칙을 따라야 네트워크 장비로서 다른 장비와 상호작용 가능

 

계층별 PDU(Process Data Unit)

1계층 - 비트

2계층 - 프레임

3계층 - 패킷

4계층 - 세그먼트

 

 

어플리케이션층에서 만들어진 data가

tcp udp 정보를 담은 세그먼트가 되고,

ip정보가 담긴 헤더가 붙은 패킷이 되고,

패킷의 정보에 이더넷 프로토콜의 정보를 담아서 프레임이되고

이 프레임이 전기적 신호로 전달됨

 

인캡슐레이션

디캡슐레이션

 

 

Encapsulation / Decapsulation

- 어플리케이션에서 만들어진 데이터가 해당 디바이스에서 네트워크를 통해 전달되는 과정

- 각 계층에서 동작하는 프로토콜별로 정보(헤더)가 추가되거나 벗겨지는 과정

 

 

어플리케이션

프레젠테이션

세션

...

 

내려가며 헤더가 붙음 -> 인캡슐레이션

이 헤더를 하나씩 떼어가며 정보를 읽는것 -> 네트워킹

 

 

어플리케이션 - 데이터 생성

- 구글검색

 

트랜스포트 - 세그먼트 생성 (세그먼트 = 포트정보+데이터)

- 디포트 : http이기에 80

- 소스포트

- 데이터

 

네트워크 레이어 - 패킷 생성 (패킷 = 세그먼트 + ip정보)

- dip(dns를 통해서 google.com의 ip를 획득하는 과정)

- 소스ip(내 ip)

- 데이터(세그먼트)

 

데이터링크 레이어 - 프레임 생성 (프레임 = 이더넷헤더 + 세그먼트)

- 이더넷헤더 추가

- dMAC(나와 연결된 같은 네트워크에서 어떤놈이 이 데이터를 받을지) (넥스트 홉)

- 소스MAC(내 기기의 MAC))

- 세그먼트

 

넥스트홉ip를 알아내는 과정을 라우팅이라고 함

라우팅 테이블을 룩업함

 

d는 destination(어디로 보낼지에 대한)

dip는 dns를 통해서 

dMAC은 라우팅과 ARP를 통해서

 

라우터는 dip를 보고 어디로 보내야할지를 결정 - 라우팅 테이블을 통해서

 

 

 

네트워크에서 출발지 - 목적지로 데이터를 전송할때 사용하는 통신방식

 

  • Unicast
    • 1대1 통신
    • 대부분 이거

 

 

 

  • Broadcast
    • 1대 N통신, 동일 네트워크에 존재하는 모든 호스트가 목적지
    • 유니캐스트로 통신하기 전 상대방의 정확한 위치를 알기위해 사용
    • 목적지가 전체이기에 과도하게 사용하면 성능저하

 

 

 

  • Multicast
    • 1대 그룹, 하나의 출발지에서 다수의 특정 목적지
    • 사내 방송같이 단방향으로 다수에게 동시에 같은 내용을 전달할때 사용

 

 

  • Anycast
    • 1대1 통신(동일 그룹 내의 1개 호스트), 다수의 동일 그룹중 가장 가까운 호스트에서 응답
    • 유니캐스트와 동일하지만 애니캐스트는 통신 가능한 다수의 후보군이 있다
    • IPv4에서는 일부기능 구현
    • IPv6에서는 모두 구현 가능

 

 

 

 

 

 

출처:

https://rooftoproom-whale.tistory.com/14

docker의 postgres에서 psql로 접속하려했더니 위와같은 권한에러가 발생했다.

 

docker compose yml에서 docker-compose up 할 때 

    environment:
      # PostgreSQL 계정 및 패스워드 설정 옵션
      PGUSER: my-user

이처럼 키값을 PSUSER로 설정해줘야한다

 

원래는 POSTGRES_USER였음

 

 

https://stackoverflow.com/questions/60193781/postgres-with-docker-compose-gives-fatal-role-root-does-not-exist-error

 

postgres with docker compose gives FATAL: role "root" does not exist error

I'm trying to create a simple demo with postgres on a local windows machine with docker desktop. This is my yaml docker compose file named img.yaml: version: '3.6' services: postgres-demo: ...

stackoverflow.com

 

 

docker system prune --all --force

+ Recent posts