N° 01 — 목록
'Backend Development' (45)
-
Backend Development/JavaJava - 21. jdbc
Statement와 PreparedStatement의 차이가 SQL Injection을 막는 이유 — JDBC 기초// Java 25 — 위험: SQL Injection 취약Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery( "SELECT * FROM users WHERE name = '" + userInput + "'");// userInput = "'; DROP TABLE users; --" → 테이블 삭제!이 코드를 작성한 개발자는 악의가 없었다. 그냥 문자열을 연결했을 뿐이다. 하지만 공격자가 '; DROP TABLE users; --를 입력하면 SQL 문이 두 개로 나뉘어 실행된다. PreparedStateme..
-
Backend Development/JavaJava - 20. virtual threads
100만 개의 스레드를 만들 수 있게 된 Java — Virtual Threads와 pinning의 함정// Java 25try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { for (int i = 0; i { Thread.sleep(Duration.ofSeconds(1)); return null; }); }} // 100만 개의 가상 스레드가 1초 만에 완료된다Java 21 이전에는 불가능했다. 100만 개의 platform thread는 각각 ~1MB 스택을 사용하여 1TB의 메모리가 필요하다. Virtual Thread는 OS 스레드가 아니라 JVM이 관리하는 경량 ..
-
Backend Development/JavaJava - 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으로 안전하게 공유하는 ..
-
Backend Development/JavaJava - 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..
-
Backend Development/JavaJava - 17. annotation-reflection
Spring이 @Autowired를 보고 의존성을 주입하는 원리 — 애너테이션과 리플렉션@Autowiredprivate UserService userService;이 코드를 실행하면 Spring은 어떻게 UserService 타입의 bean을 찾아서 userService 필드에 주입하는가? 정답은 리플렉션(reflection)이다 — 런타임에 클래스의 필드, 메서드, 애너테이션을 검사하고 조작하는 메커니즘. (Reflection API)리플렉션은 프레임워크(Spring, JUnit, Hibernate, Jackson)의 근간이지만, 잘못 쓰면 성능 저하, 캡슐화 파괴, 유지보수성 악화를 초래한다. 이 글은 애너테이션 정의, 리플렉션 API, 동적 프록시, 그리고 언제 리플렉션을 써야 하는지를 풀어간다.애..
-
Backend Development/JavaJava - 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..