| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
| 29 | 30 | 31 |
- CSS
- HashMap
- math
- vscode
- js
- input
- ArrayList
- list
- 스프링부트
- IntelliJ
- 자바문법
- java테스트
- 정규식
- 테스트자동화
- 배열
- Java
- javascript
- Visual Studio Code
- 단위테스트
- 자바스크립트
- SpringBoot
- junit5
- 인텔리제이
- string
- 문자열
- html
- 자바
- Eclipse
- Array
- junit
- Today
- Total
목록2026/03 (62)
어제 오늘 내일
서버 개발자가 가장 많이 하는 실수 중 하나가 "DB 커넥션 풀 설정을 기본값(Default)으로 두는 것"입니다.HikariCP의 기본 최대 연결 수는 10개입니다. 트래픽이 적을 땐 문제없지만, 조금만 몰려도 11번째 사용자는 하염없이 기다리다가 타임아웃 에러를 맞게 됩니다.그렇다면 무조건 많이 늘리면 될까요? 아니요. 너무 많으면 오히려 느려집니다.오늘은 HikariCP의 동작 원리와 최적의 풀 사이즈(Pool Size)를 구하는 공식을 알아보겠습니다.1. 커넥션 풀(Connection Pool)이 뭔가요?DB 연결(TCP Connection)을 맺는 과정은 비용이 매우 비쌉니다. (3-way handshake 등)사용자가 올 때마다 연결을 새로 만들면 서버는 금방 지칩니다.그래서 미리 연결(Con..
열심히 만든 서버를 배포하고 퇴근했는데, 새벽에 알람이 울립니다. "서버 다운".부랴부랴 접속해서 로그를 보지만, 아무것도 없습니다. java.lang.OutOfMemoryError: Java heap space 이 에러는 JVM의 힙(Heap) 메모리가 꽉 차서 더 이상 객체를 만들 수 없을 때 발생합니다. 문제는 JVM 자체가 멈추기 때문에 로그를 남길 힘조차 없다는 것입니다.이때 필요한 것이 바로 힙 덤프(Heap Dump)입니다.1. 힙 덤프(Heap Dump)가 뭔가요?쉽게 말해 "서버가 죽기 직전의 메모리 스냅샷"입니다.어떤 객체가 메모리를 몇 GB나 차지하고 있었는지, 누가 그 객체를 참조하고 있었는지를 낱낱이 기록한 파일(hprof)입니다.이 파일만 있으면 범인을 100% 잡을 수 있습니..
"서버가 왜 죽었죠?""몰라요... 로그가 다 날아갔어요..."이런 대화가 오간다면 그 서버는 시한폭탄입니다. System.out.println은 동기 방식(Blocking I/O)이라 서버 성능을 갉아먹고, 결정적으로 파일로 남지 않아서 서버를 끄면 로그도 사라집니다.스프링 부트의 기본 로깅 라이브러리인 Logback을 제대로 설정해서, "에러는 파일로 남기고, 30일 지난 로그는 알아서 지우는" 스마트한 시스템을 구축해 봅시다.1. 로그 레벨 (Log Level) 이해하기로그백은 중요도에 따라 5단계 레벨을 가집니다.TRACE: 나노 단위의 추적 (가장 상세함)DEBUG: 개발할 때 필요한 정보 (SQL 쿼리, 파라미터 등)INFO: 운영 시스템에서 봐야 할 정보 (서버 시작, 종료, 비즈니스 로직 ..
프론트엔드에서 데이터를 보낼 때, 우리는 절대 그 데이터를 믿으면 안 됩니다. 해커가 이상한 값을 보낼 수도 있고, 사용자가 실수를 할 수도 있으니까요.하지만 그렇다고 모든 메서드에 검증 로직을 넣는 건 최악입니다.// ❌ 최악의 코드 (if문 지옥)if (dto.getEmail() == null || !dto.getEmail().contains("@")) { throw new IllegalArgumentException("이메일 형식이 아닙니다.");}if (dto.getAge() 스프링 부트는 이 귀찮은 작업을 Bean Validation이라는 표준 기술로 해결해 줍니다.1. 설정하기 (의존성 추가)스프링 부트 2.3 버전 이상부터는 validation 라이브러리가 별도로 분리되었습니다. bui..
우리는 보통 테스트할 때 빠르고 간편한 H2 데이터베이스(In-memory)를 사용합니다. 하지만 운영 환경은 MySQL이나 PostgreSQL을 쓰죠. 여기서 치명적인 문제가 발생합니다. MySQL: INSERT IGNORE... (지원함) H2: "그게 뭐죠? 에러 뿜!" (지원 안 함, 혹은 문법 다름) 결국 "테스트는 통과했지만 배포하면 망하는" 시한폭탄을 안고 가는 셈입니다.이 문제를 해결하기 위해 등장한 것이 바로 Testcontainers입니다.1. Testcontainers가 뭔가요?자바 코드(JUnit)에서 Docker 컨테이너를 직접 제어하는 라이브러리입니다. 테스트가 시작되면 (@BeforeAll) 도커로 진짜 MySQL 컨테이너를 띄웁니다. 테스트를 수행합니다. 테스트가 ..
서버 개발을 하다 보면 다른 서버(네이버, 카카오, 혹은 사내 다른 팀 서버)에 API 요청을 보내야 할 때가 있습니다.보통 RestTemplate이나 WebClient를 쓰는데, 코드가 이렇습니다.// ❌ RestTemplate의 악몽 (URL 만들고, 헤더 넣고, 요청 보내고...)String url = "https://api.weather.com/v1/forecast?city=seoul";HttpHeaders headers = new HttpHeaders();headers.add("Authorization", "Bearer token");HttpEntity entity = new HttpEntity(headers);ResponseEntity response = restTemplate.exchange..
스프링 부트 3.x 버전부터는 Java 17 이상이 필수입니다. 그런데 아직도 Java 8 스타일로 코딩하고 계신가요?오늘은 여러분의 코드를 절반으로 줄여줄 마법 같은 문법들을 소개합니다. (이걸 알면 다시는 예전으로 못 돌아갑니다.)1. DTO의 혁명: 레코드 (Record)DTO(Data Transfer Object)를 만들 때마다 private final, 생성자, getter, equals, hashCode, toString... 지겨우셨죠? 롬복(@Data)을 써도 되지만, 이제는 자바가 순정 기능으로 지원합니다.❌ Before (Java 11 이하 / 롬복)@Getter@RequiredArgsConstructorpublic class MemberDto { private final Stri..
프로젝트를 시작할 때 가장 귀찮은 게 뭘까요? 바로 로컬 환경 세팅입니다.MySQL 깔고, Redis 깔고, RabbitMQ 깔고... 버전 맞추고 포트 충돌 해결하다 보면 하루가 다 갑니다.게다가 팀원 A는 윈도우, 팀원 B는 맥(Mac)을 쓴다면? "제 컴퓨터에선 되는데요?"라는 핑계가 난무하게 되죠.오늘은 이 모든 문제를 Docker(도커)와 Docker Compose(도커 컴포즈)로 한 방에 해결하는 법을 알아보겠습니다.1. 도커(Docker)가 뭔가요? (도시락 비유)도커는 프로그램을 컨테이너(Container)라는 격리된 상자에 담는 기술입니다.기존 방식: 내 컴퓨터에 MySQL 설치 (내 OS 설정에 영향받음)도커 방식: MySQL이 완벽하게 세팅된 '도시락(Image)'을 다운받아서 뚜껑만..
개발하다 보면 "핵심 로직"과 "부가 로직"이 섞일 때가 있습니다.가장 대표적인 예가 회원가입입니다.회원 정보 DB 저장 (핵심 - 0.1초)가입 축하 메일 발송 (부가 - 3초)가입 축하 쿠폰 발행 (부가 - 0.5초)이걸 한 트랜잭션으로 묶어서 순차적으로 실행하면, 사용자는 가입 완료까지 총 3.6초를 기다려야 합니다. 만약 메일 서버가 죽으면? 가입 자체가 롤백되어 버리는 대참사가 일어납니다.오늘은 이 "기다림"을 없애는 비동기 처리와, 서비스 간의 의존성을 끊어내는 이벤트 기반 설계를 알아보겠습니다.1. 나중에 해! 비동기 처리 ()가장 쉬운 해결책은 "메일 발송은 다른 쓰레드(Thread)가 알아서 하고, 넌 바로 응답해!"라고 하는 것입니다. 스프링은 어노테이션 하나로 이걸 지원합니다.① 설정..
개발을 하다 보면 이런 고민에 빠집니다."DB 테이블이랑 똑같은 클래스(Entity)가 있는데, 굳이 또 DTO(Data Transfer Object)를 만들어야 하나요?"귀찮아서 그냥 Entity를 반환해 버리면 당장은 편하지만, 나중에 치명적인 보안 문제와 무한 루프(Circular Reference)에 빠지게 됩니다. 오늘은 왜 DTO를 써야 하는지, 그리고 변환은 어디서 하는 게 정석인지 명쾌하게 정리해 드립니다.1. Entity를 절대 밖으로 꺼내지 마세요!@Entity가 붙은 클래스는 데이터베이스 그 자체입니다. 이걸 컨트롤러에서 그대로 반환(return entity)하면 안 되는 3가지 이유가 있습니다.API 스펙이 DB에 종속됨: DB 컬럼명을 바꾸면 API 스펙도 강제로 바뀝니다. (프론..
