Develop Artifacts/Java

Java - 19. concurrent

new Thread()를 직접 만드는 것을 멈춰야 하는 이유 — Executor와 CompletableFuture100개의 HTTP 요청을 병렬로 보내야 한다. new Thread()를 100개 만들까? — OS 스레드는 메모리를 1MB씩 소비하므로(스택 크기), 100개는 100MB다. 게다가 스레드 생성/소멸 비용이 매번 발생한다. ExecutorService를 쓰면 스레드 풀을 재사용하여 이 비용을 없앤다. (java.util.concurrent 패키지)100개의 HTTP 요청을 보내야 한다. new Thread() 100개? OS 스레드는 1MB씩 잡아먹는다. 이 글은 스레드 풀로 재사용하고, CompletableFuture로 비동기를 엮고, ConcurrentHashMap으로 안전하게 공유하는 ..

Develop Artifacts/Java

Java - 18. thread sync

두 스레드가 count++를 동시에 실행하면 값이 1만 증가하는가 — 가시성과 원자성// Java 25class Counter { private int count = 0; public void increment() { count++; }}두 스레드가 동시에 counter.increment()를 10,000번씩 호출하면 count가 20,000이 될까? — 아니다. 대부분 17,000~19,000 사이의 값이 나온다. count++는 하나의 연산처럼 보이지만, 실제로는 읽기 → 더하기 → 쓰기 세 단계이며, 두 스레드가 동시에 같은 값을 읽으면 하나의 증가가 사라진다(lost update).이것이 경쟁 조건(race condition)이다. 이 글은 Java 메모리 모델(JMM), synchro..

Develop Artifacts/Java

Java - 17. annotation-reflection

Spring이 @Autowired를 보고 의존성을 주입하는 원리 — 애너테이션과 리플렉션@Autowiredprivate UserService userService;이 코드를 실행하면 Spring은 어떻게 UserService 타입의 bean을 찾아서 userService 필드에 주입하는가? 정답은 리플렉션(reflection)이다 — 런타임에 클래스의 필드, 메서드, 애너테이션을 검사하고 조작하는 메커니즘. (Reflection API)리플렉션은 프레임워크(Spring, JUnit, Hibernate, Jackson)의 근간이지만, 잘못 쓰면 성능 저하, 캡슐화 파괴, 유지보수성 악화를 초래한다. 이 글은 애너테이션 정의, 리플렉션 API, 동적 프록시, 그리고 언제 리플렉션을 써야 하는지를 풀어간다.애..

Develop Artifacts/Java

Java - 16. io nio

Files.readAllLines()가 파일이 10GB일 때 OOM을 내는 이유 — I/O 모델의 선택10GB 파일을 Files.readAllLines()로 읽었다. 파일이 작을 때는 잘 동작한다. 하지만 10GB 파일에서는 OutOfMemoryError가 발생한다 — 모든 줄을 메모리에 한 번에 올리기 때문이다. Files.lines()를 쓰면 한 줄씩 스트리밍으로 읽으므로 OOM 없이 처리할 수 있다. (Files API)10GB 파일을 읽었더니 OutOfMemoryError가 났다. 왜? 전체 파일을 메모리에 올렸기 때문이다. 이 글은 Files.lines()로 스트리밍 읽기를 하는 법, Path로 파일을 다루는 법, 그리고 레거시 java.io를 버려야 하는 이유를 풀어간다.java.io vs j..

Develop Artifacts/Java

Java - 15. datetime

new Date()가 1900년을 더해야 하는 이유 — java.time이 해결한 날짜 API의 재앙// Java 1.1 (1997년)Date d = new Date(2024 - 1900, 1 - 1, 1);// 연도에서 1900을 빼고, 월은 0부터 시작 — 상식과 정반대이 API는 Java 1.0(1996년)에서 만들어졌고, 30년이 지나도 여전히 레거시 코드에 남아 있다. java.util.Date의 월은 0부터 시작하고, 연도는 1900을 빼야 하며, SimpleDateFormat은 thread-safe하지 않다. Java 8(2014년)의 java.time 패키지(JEP-150, JSR-310)가 이 재앙을 끝냈다. (java.time 패키지)이 글은 java.time의 핵심 타입들 — Inst..

Develop Artifacts/Java

Java - 14. optional

Optional.get()를 호출하면 NPE가 없어지는가 — Optional의 설계 의도와 함정Optional를 도입하면 NullPointerException이 사라질까? — 아니다. Optional.get()을 빈 Optional에 호출하면 NoSuchElementException이 발생한다. Optional은 null을 없애는 도구가 아니라, "값이 없을 수 있다"는 사실을 타입 시스템으로 표현하는 도구다. (Optional API)"값이 없을 수도 있다"는 사실을 타입으로 표현하면 어떻게 될까? 이 글은 Optional이 NPE를 어떻게 예방하는지, 언제 쓰고 언제 쓰지 말아야 하는지를 풀어간다.Optional이 해결하는 문제 — "이 메서드는 null을 반환할 수 있습니다"Java 8 이전에는 메..

Archive

'Java' 24

Develop Artifacts/Java

Java - 19. concurrent

new Thread()를 직접 만드는 것을 멈춰야 하는 이유 — Executor와 CompletableFuture100개의 HTTP 요청을 병렬로 보내야 한다. new Thread()를 100개 만들까? — OS 스레드는 메모리를 1MB씩 소비하므로(스택 크기), 100개는 100MB다. 게다가 스레드 생성/소멸 비용이 매번 발생한다. ExecutorService를 쓰면 스레드 풀을 재사용하여 이 비용을 없앤다. (java.util.concurrent 패키지)100개의 HTTP 요청을 보내야 한다. new Thread() 100개? OS 스레드는 1MB씩 잡아먹는다. 이 글은 스레드 풀로 재사용하고, CompletableFuture로 비동기를 엮고, ConcurrentHashMap으로 안전하게 공유하는 ..

댓글
Develop Artifacts/Java

Java - 18. thread sync

두 스레드가 count++를 동시에 실행하면 값이 1만 증가하는가 — 가시성과 원자성// Java 25class Counter { private int count = 0; public void increment() { count++; }}두 스레드가 동시에 counter.increment()를 10,000번씩 호출하면 count가 20,000이 될까? — 아니다. 대부분 17,000~19,000 사이의 값이 나온다. count++는 하나의 연산처럼 보이지만, 실제로는 읽기 → 더하기 → 쓰기 세 단계이며, 두 스레드가 동시에 같은 값을 읽으면 하나의 증가가 사라진다(lost update).이것이 경쟁 조건(race condition)이다. 이 글은 Java 메모리 모델(JMM), synchro..

댓글
Develop Artifacts/Java

Java - 17. annotation-reflection

Spring이 @Autowired를 보고 의존성을 주입하는 원리 — 애너테이션과 리플렉션@Autowiredprivate UserService userService;이 코드를 실행하면 Spring은 어떻게 UserService 타입의 bean을 찾아서 userService 필드에 주입하는가? 정답은 리플렉션(reflection)이다 — 런타임에 클래스의 필드, 메서드, 애너테이션을 검사하고 조작하는 메커니즘. (Reflection API)리플렉션은 프레임워크(Spring, JUnit, Hibernate, Jackson)의 근간이지만, 잘못 쓰면 성능 저하, 캡슐화 파괴, 유지보수성 악화를 초래한다. 이 글은 애너테이션 정의, 리플렉션 API, 동적 프록시, 그리고 언제 리플렉션을 써야 하는지를 풀어간다.애..

댓글
Develop Artifacts/Java

Java - 16. io nio

Files.readAllLines()가 파일이 10GB일 때 OOM을 내는 이유 — I/O 모델의 선택10GB 파일을 Files.readAllLines()로 읽었다. 파일이 작을 때는 잘 동작한다. 하지만 10GB 파일에서는 OutOfMemoryError가 발생한다 — 모든 줄을 메모리에 한 번에 올리기 때문이다. Files.lines()를 쓰면 한 줄씩 스트리밍으로 읽으므로 OOM 없이 처리할 수 있다. (Files API)10GB 파일을 읽었더니 OutOfMemoryError가 났다. 왜? 전체 파일을 메모리에 올렸기 때문이다. 이 글은 Files.lines()로 스트리밍 읽기를 하는 법, Path로 파일을 다루는 법, 그리고 레거시 java.io를 버려야 하는 이유를 풀어간다.java.io vs j..

댓글
Develop Artifacts/Java

Java - 15. datetime

new Date()가 1900년을 더해야 하는 이유 — java.time이 해결한 날짜 API의 재앙// Java 1.1 (1997년)Date d = new Date(2024 - 1900, 1 - 1, 1);// 연도에서 1900을 빼고, 월은 0부터 시작 — 상식과 정반대이 API는 Java 1.0(1996년)에서 만들어졌고, 30년이 지나도 여전히 레거시 코드에 남아 있다. java.util.Date의 월은 0부터 시작하고, 연도는 1900을 빼야 하며, SimpleDateFormat은 thread-safe하지 않다. Java 8(2014년)의 java.time 패키지(JEP-150, JSR-310)가 이 재앙을 끝냈다. (java.time 패키지)이 글은 java.time의 핵심 타입들 — Inst..

댓글
Develop Artifacts/Java

Java - 14. optional

Optional.get()를 호출하면 NPE가 없어지는가 — Optional의 설계 의도와 함정Optional를 도입하면 NullPointerException이 사라질까? — 아니다. Optional.get()을 빈 Optional에 호출하면 NoSuchElementException이 발생한다. Optional은 null을 없애는 도구가 아니라, "값이 없을 수 있다"는 사실을 타입 시스템으로 표현하는 도구다. (Optional API)"값이 없을 수도 있다"는 사실을 타입으로 표현하면 어떻게 될까? 이 글은 Optional이 NPE를 어떻게 예방하는지, 언제 쓰고 언제 쓰지 말아야 하는지를 풀어간다.Optional이 해결하는 문제 — "이 메서드는 null을 반환할 수 있습니다"Java 8 이전에는 메..

댓글

wall

방명록

방문 흔적을 남겨주세요. 질문이나 인사 모두 환영합니다.