교육자
전: 우아한형제들 기술이사, 카카오, SK플래닛
진짜 실무에 필요한 제대로 된 개발자가 될 수 있도록, 교육하는 것이 저의 목표입니다.
저의 개발 인생 이야기
EO 인터뷰 영상
개발바닥 - 시골 청년 개발왕 되다
취업과 이직에 대한 고민 해결
Khóa học
Đánh giá khóa học
- Nhập môn Java của Kim Young-han - Bước đầu tiên học Java bằng code
- Nhập môn Java của Kim Young-han - Bước đầu tiên học Java bằng code
- Thực chiến Java của Kim Young-han - Nâng cao phần 3, Lambda, Stream, Lập trình hàm
- Cơ sở dữ liệu thực chiến của Kim Young-han - Phiên bản cơ bản
rtkof0030
·
Nhập môn cơ sở dữ liệu thực chiến của Kim Young-han - Bước đầu SQL cho mọi người IT (Từ SQL một cách từng bước)Nhập môn cơ sở dữ liệu thực chiến của Kim Young-han - Bước đầu SQL cho mọi người IT (Từ SQL một cách từng bước)
Bài viết
Hỏi & Đáp
[자료 패키지 누락] 2.람다 자료에서 문제 패키지명 생략 (25page)
류정균님 감사합니다 🙂다음 패치에 반영할게요^^!
- 0
- 2
- 17
Hỏi & Đáp
drop과 truncate
안녕하세요. Alex Kim님정리하면 다음과 같습니다 🙂DROP: 테이블 자체를 완전히 제거TRUNCATE: 테이블은 유지하고 그 안에 있는 데이터를 모두 제거, 매우 빠르지만 롤백 불가능DELETE: 원하는 데이터를 선택해서 제거, 느리지만, 롤백 가능감사합니다.
- 0
- 1
- 26
Hỏi & Đáp
지연 평가
안녕하세요. tmdwhd319님원시값의 경우 원시값 byte만 차지합니다.참조 값의 경우 메모리 사용량은 '주소값' + '힙에 있는 실제 객체의 크기'가 됩니다.람다의 경우 참조값과 마찬가지로, 람다 객체를 가리키는 '주소값'과 '힙에 생성된 람다 객체'가 메모리를 차지합니다. (람다의 경우 캡처하는 변수가 없다면 약 20바이트 정도의 아주 적은 메모리만 차지합니다.)추가로 CPU와 메모리는 서로 다른 리소스이기 때문에 둘을 비교하기는 어렵습니다.그래도 어떤 로직이든 호출되는 것 보다는 호출되지 않는 쪽이 전체적인 리소스 사용이 훨씬 덜하게 됩니다.감사합니다.
- 0
- 1
- 17
Hỏi & Đáp
AopCheck Test 부분의 EnhancerBySpring 확인 법??
안녕하세요. Minho Lee님스프링의 버전에 따라서 해당 키워드들이 달리 나올 수 있습니다.화면에 보이는 SpringCGLIB라고 보이면 적용된 것으로 이해하시면 됩니다 🙂다음 패치에 메뉴얼에도 반영해둘게요 🙂감사합니다.
- 0
- 2
- 23
Hỏi & Đáp
중급2편 56강의 bucket.add(value); 메서드가 이해가 안됩니다.
안녕하세요. 김종창님해당 코드는 자바 라이브러리에 있는 LinkedList 클래스의 add() 메서드입니다.자세한 내용은 다음과 같습니다:1. buckets 배열의 선언: MyHashSetV1 클래스를 보면, LinkedList[] buckets;와 같이 buckets 변수가 LinkedList 객체들의 배열로 선언되어 있습니다.2. buckets 초기화: initBuckets() 메서드에서는 이 buckets 배열의 각 인덱스에 new LinkedList();를 통해 새로운 LinkedList 인스턴스를 할당하고 있습니다.3. bucket 변수: add(int value) 메서드 내부에서 LinkedList bucket = buckets[hashIndex];와 같이 hashIndex에 해당하는 buckets 배열의 요소를 bucket 변수에 할당합니다. 이 bucket은 java.util.LinkedList 타입의 객체입니다.4. bucket.add(value);: 따라서 bucket.add(value); 코드는 java.util.LinkedList 객체인 bucket의 add() 메서드를 호출하여 value를 해당 연결 리스트의 끝에 추가하는 것입니다.이전에 강의에서 보셨던 inputArray = 1;와 같이 직접 배열 인덱스에 값을 대입하는 방식은 기본 배열(primitive array)에 값을 저장할 때 사용됩니다. 하지만 MyHashSetV1에서는 해시 충돌을 처리하기 위해 배열의 각 인덱스에 또 다른 자료구조인 LinkedList를 사용하고 있으며, 이 LinkedList에 add() 메서드를 통해 데이터를 저장하는 것입니다.LinkedList는 자바 컬렉션 프레임워크의 일부로, 크기가 동적으로 변할 수 있는 리스트 자료 구조입니다. 이 add() 메서드는 LinkedList의 기능을 활용하여 요소를 추가하는 표준적인 방법입니다.감사합니다.
- 0
- 3
- 28
Hỏi & Đáp
limit, offset 에서 인덱스 동작
안녕하세요. bebe님결론부터 말씀드리면, DBMS는 LIMIT와 OFFSET을 처리할 때 기본적으로 인덱스를 그대로 활용하지만, OFFSET 값이 커질수록 성능 저하가 발생하여 특별한 최적화 기법이 필요할 수 있습니다. 질문해주신 내용을 바탕으로 하나씩 자세히 설명해 드릴게요.ORDER BY 절에 사용된 칼럼에 인덱스가 있다면, 데이터베이스는 인덱스를 통해 정렬된 순서대로 데이터에 접근하므로 Filesort를 피할 수 있습니다.LIMIT와 OFFSET이 포함된 쿼리는 다음과 같은 방식으로 인덱스를 활용하여 동작합니다.인덱스 스캔 시작: ORDER BY 절의 칼럼 인덱스(예: 생성일 인덱스)를 처음부터 순차적으로 스캔합니다.OFFSET 만큼 건너뛰기: 데이터베이스는 인덱스의 리프 노드를 따라가며 OFFSET에 지정된 수만큼의 데이터를 읽고 버립니다. 여기서 중요한 점은 데이터를 읽기는 한다는 것입니다.LIMIT 만큼 반환: OFFSET 수만큼 데이터를 건너뛴 후, LIMIT에 지정된 수만큼의 데이터를 가져와 사용자에게 반환합니다.즉, 궁금해하신 "n번째 칼럼을 빠르게 알아내는" 특별한 방법이 있는 것은 아닙니다. DBMS는 인덱스를 처음부터 훑으면서 OFFSET 개수만큼의 데이터를 일일이 건너뛰는 방식으로 동작합니다.OFFSET이 커질 때 발생하는 문제점과 해결 방안이러한 동작 방식 때문에 OFFSET 값이 작을 때는 매우 효율적이지만, OFFSET 값이 수백만, 수천만에 달하는 "뒤쪽 페이지"로 갈수록 심각한 성능 저하가 발생합니다. 예를 들어 OFFSET 10000000, LIMIT 20 이라는 쿼리는 20개의 데이터를 가져오기 위해 무려 10,000,000개의 데이터를 인덱스로 스캔하고, 테이블에서 읽어온 뒤 버려야 하기 때문입니다.이때 언급하신 커버링 인덱스가 1차적인 해결책이 될 수 있습니다. 쿼리에 필요한 모든 칼럼이 인덱스에 포함되어 있다면, 데이터 테이블에 접근하는 Random I/O를 피하고 인덱스 내에서만 데이터를 읽고 버릴 수 있어 성능이 향상됩니다.하지만 커버링 인덱스만으로는 OFFSET이 매우 클 때 발생하는 대량의 불필요한 스캔 자체를 막을 수는 없습니다. 이를 해결하기 위한 더 근본적인 방법은 OFFSET을 사용하지 않는 방식으로 페이징을 구현하는 것입니다. 이를 "커서 기반 페이징(Cursor-based Pagination)" 또는 "Seek Method"라고 부릅니다.커서 기반 페이징 (Seek Method)이 방식은 마지막으로 조회된 페이지의 마지막 값을 기억해두었다가, 다음 페이지를 조회할 때 그 값을 WHERE 조건절에 사용하는 것입니다.기존 OFFSET 방식:SELECT * FROM posts ORDER BY created_at DESC LIMIT 20 OFFSET 10000000; 커서 기반 페이징 방식:-- 이전 페이지에서 마지막으로 보았던 created_at 값이 '2023-10-27 10:00:00' 이었다고 가정SELECT * FROM postsWHERE created_at ORDER BY created_at DESCLIMIT 20; -- OFFSET 없이 바로 20개 조회 이렇게 하면 DBMS는 created_at 인덱스에서 '2023-10-27 10:00:00' 위치를 바로 찾은 뒤, 그 지점부터 20개의 데이터만 스캔하면 되므로 수천만 개의 데이터를 버리는 비효율적인 작업을 피할 수 있습니다. OFFSET을 사용하는 것보다 훨씬 빠르고 효율적인 방법입니다.관련해서 커서 기반 페이징(Cursor-based Pagination)을 검색해보시면 도움이 되실거에요.감사합니다.
- 0
- 2
- 39
Hỏi & Đáp
섹션 14. 115번 강의 내용 질문
안녕하세요. jjs270402님이 설명은 해당 테스트 시나리오에서는 큐가 의도적으로 1000개까지 채워졌다는 것을 전제로 합니다. 큐가 가득 찼기 때문에 스레드 풀은 설정된 최대 스레드 개수(200개, 즉 기본 스레드 100개 외에 100개의 '초과 스레드')까지 확장되어 긴급 투입이 발생한 것입니다.실제 동적인 환경에서는 작업 처리 속도와 작업 유입 속도에 따라 스레드 풀의 동작이 달라질 수 있습니다. 만약 기본 스레드(100개)의 작업 처리 속도가 매우 빨라서 큐에 작업이 1000개까지 쌓이기 전에 빠르게 소진된다면, 큐가 가득 차지 않아 최대 스레드 개수까지 스레드가 긴급 투입되지 않을 수도 있습니다. 즉, 코어 스레드와 큐의 용량만으로도 충분히 작업을 처리할 수 있는 시나리오가 발생할 수 있습니다.감사합니다.
- 0
- 2
- 25
Hỏi & Đáp
문제1번 수정건의
김태언님 감사합니다 🙂메뉴얼에 언급해두어야겠네요.다음 패치에 반영하겠습니다^^!
- 0
- 1
- 39
Hỏi & Đáp
Executor 스레드 풀 관리 질문
안녕하세요. 김정민님실무에서 이미 운영중인 서비스의 스레드 풀을 직접 늘리는 방식을 사용하지는 않습니다.왜냐하면 어차피 서버에서 제공하는 리소스(CPU, 메모리)는 한정이 있기 때문입니다.실무에서는 성능 테스트를 통해 이런 값들은 처음부터 사용하는 리소스에 맞추어 최적화해두고, 대신에 사용자가 늘어나면 서버 자체를 실시간으로 더 투입하는 방식으로 문제를 해결합니다.감사합니다.
- 0
- 2
- 49
Hỏi & Đáp
문제와 풀이 질문!
안녕하세요. 김정민님List> tasks를 외부에서 주입 받아서 사용하는 방식으로 코드를 개선할 수 있을 것 같아요. 그러면 InventoryWork, ShippingWork, AccountingWork와 같은 코드가 늘어도 NewOrderService 클래스는 손대지 않아도 되겠지요?참고로 스프링 핵심원리 기본편 강의에 가면 궁금하신 비슷한 예시를 학습할 수 있습니다 🙂감사합니다.감사합니다.
- 0
- 1
- 34