Framework (60) 썸네일형 리스트형 [Spring Boot] 커넥션 풀(HikariCP) 튜닝: 병목을 뚫고 장애를 예방하는 인프라의 심장 여러분이 인기 아이돌 콘서트 티켓팅 사이트의 백엔드 개발자라고 상상해 봅시다. 밤 8시 정각, 1만 명의 유저가 동시에 '결제하기' 버튼을 누릅니다. 스프링 부트(Spring Boot) 서버는 무사히 요청을 받았지만, 데이터베이스(DB)에 접속하려다 보니 심각한 문제가 발생합니다. 애플리케이션이 DB와 TCP/IP 통신을 맺고 로그인하는 과정은 엄청나게 무겁고 긴 시간이 소요됩니다. 1만 명이 접속할 때마다 매번 이 연결(Connection)을 새로 맺는다면 DB 서버는 10초도 안 돼서 뻗어버릴 것입니다. 이 끔찍한 병목(Bottleneck) 현상을 해결하기 위해 "미리 DB와의 연결(통로) 100개를 맺어놓고, 유저가 올 때마다 빌려주고 다시 반납받는 대여소"를 만들었는데, 이것이 바로 커넥션 풀(C.. [Spring Boot] QueryDSL 입문: 타입 세이프(Type-safe)한 동적 쿼리의 끝판왕 10단계에서 배운 Spring Data JPA의 Query Method와 @Query는 훌륭했지만, 실무의 거친 요구사항을 만나면 한계가 명확하게 드러납니다. 쇼핑몰의 상품 검색창을 생각해 봅시다. 사용자는 '상품명'만 검색할 수도 있고, '가격 범위'만 필터링할 수도 있으며, '카테고리'와 '브랜드'를 동시에 선택할 수도 있습니다. 즉, 조건이 있을 수도 있고 없을 수도 있는 '동적 쿼리(Dynamic Query)'가 필요합니다. 과거 MyBatis 시절에는 XML 파일에 같은 태그를 수십 개 도배하여 쿼리 문자열(String)을 조립했습니다. JPA @Query에서 문자열로 동적 쿼리를 짜다 보면 띄어쓰기 하나 잘못해서 서버가 켜진 뒤 고객이 검색 버튼을 누르는 순간 에러가 터집니다(런타임 에러)... [Spring Boot] Spring Data JPA의 마법: QueryMethod로 검색과 페이징을 박살내다 과거 JPA(Hibernate)만 순수하게 쓰던 시절에는 개발자가 직접 EntityManager를 불러와서 em.persist(), em.find() 같은 코드를 짰습니다. 이 정도만 해도 SQL을 안 짜서 행복했지만, 스프링 진영은 여기서 만족하지 않았습니다. "아니, 저장하고 찾고 삭제하는 CRUD 코드는 전 세계 모든 프로젝트가 다 똑같은데, 개발자가 왜 굳이 그 코드를 또 짜야 해? 우리가 다 만들어 줄게!"라는 미친 발상에서 탄생한 괴물이 바로 Spring Data JPA입니다. 이제 우리는 그저 JpaRepository라는 인터페이스 하나를 상속받는 것만으로 수십 개의 기본 쿼리 기능이 하늘에서 뚝 떨어지는 기적을 맛봅니다. 하지만 진짜 마법은 지금부터입니다. 만약 "나이가 20살 이상이고 이.. [Spring Boot] JPA 연관관계 매핑 실전: 1:N 설계와 공포의 N+1 문제 정복 8단계에서 JPA의 신세계를 맛본 개발자들은 흥분에 차서 이렇게 외칩니다. "와! SQL 안 짜고 @Entity 하나만 달면 끝이네! 이제 JPA 마스터다!" 그러나 그 오만함은 실무의 복잡한 비즈니스 모델을 만나는 순간 처참히 박살 납니다. 현실의 데이터베이스는 단일 테이블로 존재하지 않습니다. 하나의 회원(Member)은 여러 개의 주문(Order)을 할 수 있고, 하나의 게시글(Post)에는 수많은 댓글(Comment)이 달립니다. RDB는 '외래 키(Foreign Key)' 하나로 이 관계를 멋지게 풀지만, 자바(Java) 객체는 서로의 '참조(Reference)'를 가져야만 관계가 맺어집니다. 여기서 발생하는 패러다임의 충돌을 해결하는 것이 바로 JPA의 꽃이라 불리는 '연관관계 매핑(Assoc.. [Spring Boot] JPA(Hibernate) 기초: 객체와 관계형 DB의 패러다임 불일치를 부수다 과거의 자바(Java) 백엔드 개발자들은 하루 종일 무엇을 했을까요? "SQL 작성 기계"였습니다. 게시판 하나를 만들려 해도 INSERT INTO board VALUES..., SELECT * FROM board WHERE... 등 길고 지루한 SQL 쿼리문을 수백 줄씩 타이핑해야 했습니다. 만약 중간에 DB 테이블에 컬럼이 하나라도 추가되면, 그 수백 줄의 쿼리문을 일일이 다 찾아다니며 수정하는 끔찍한 '노가다'의 연속이었죠. 게다가 객체 지향 언어인 자바(Java)와 관계형 데이터베이스(RDB)는 태생적으로 사상(Paradigm)이 너무나도 달랐습니다. 자바는 '상속'과 '참조'를 사랑하지만, DB는 그냥 2차원 표(Table)일 뿐이니까요. 이 극악무도한 '패러다임의 불일치'를 박살내고, 개발자가.. [Spring Boot] 전역 예외 처리(Global Exception Handling): 에러의 혼돈을 우아하게 제압하라 우리가 정성스럽게 만든 REST API 서버가 실제 세상에 배포되는 순간, 상상을 초월하는 사용자(Client)들을 만나게 됩니다. 숫자가 들어가야 할 나이 필드에 '스물다섯'이라는 문자를 던지거나, 존재하지 않는 user_id=999를 집요하게 요청하는 등 무수한 공격과 실수가 쏟아집니다. 이때 서버 내부에서 NullPointerException이나 IllegalArgumentException 같은 자바 에러가 터지면 어떻게 될까요? 스프링 부트(Spring Boot)는 아무 설정을 안 하면 시뻘건 스택 트레이스(Stack Trace) 로그와 함께 아주 끔찍하고 못생긴 "Whitelabel Error Page"나 알 수 없는 HTML 덩어리를 응답으로 뱉어냅니다. 만약 프론트엔드(React, Vue) .. [Spring Boot] 의존성 주입(DI)과 IoC 컨테이너: 객체의 생과 사를 스프링에게 맡기다 우리가 자바(Java) 학원에서 처음 프로그래밍을 배울 때, 어떤 클래스의 기능을 사용하려면 무조건 new 키워드를 사용해 메모리에 객체를 찍어내야 한다고 배웠습니다. 예를 들어 UserService에서 UserRepository가 필요하면 UserRepository repository = new UserRepository(); 처럼 직접 생성했습니다. 하지만 실무 스프링 부트(Spring Boot) 프로젝트 코드를 아무리 뒤져봐도 new 키워드를 찾아보기는 하늘의 별 따기입니다. 개발자가 객체를 직접 만들지 않는데 도대체 프로그램이 어떻게 굴러가는 걸까요? 이 거대한 미스터리를 푸는 열쇠이자, 전 세계 수많은 자바 개발자들을 스프링의 노예(?)로 만들어버린 가장 위대하고 핵심적인 철학이 바로 IoC(I.. [Spring Boot] Logback 완벽 가이드: 서버의 유일한 목격자, 로깅(Logging) 마스터하기 초보 개발자와 실무 개발자를 구분하는 가장 확실한 기준 하나를 꼽으라면 바로 '로깅(Logging)을 어떻게 다루는가?'입니다. 대학생이나 학원 시절 프로젝트에서는 에러가 나거나 변수 값을 확인하고 싶을 때 무조건 System.out.println("여기로 들어옴!!")을 난사했습니다. 하지만 실제 운영(Production) 서버에서 System.out.println을 쓰면, 치명적인 성능 저하(블로킹 I/O)가 발생할 뿐만 아니라, 서버가 재시작되는 순간 콘솔에 찍힌 글자들이 흔적도 없이 증발해 버립니다. 어젯밤 11시에 결제가 실패해서 고객센터로 항의가 들어왔는데, 원인을 찾으려고 보니 로그 기록이 완전히 날아가 있다면 개발자는 등골이 오싹해질 수밖에 없습니다.이번 [Spring Boot 실무 완벽 .. [Spring Boot] application.yml 완벽 가이드: Profile을 활용한 무결점 환경 분리 전략 스프링 부트(Spring Boot)로 개발을 진행하다 보면 필연적으로 데이터베이스 접속 IP, 비밀번호, 외부 결제 API 연동 키(Key) 등 수많은 '설정(Configuration) 데이터'를 다루게 됩니다. 초보 개발자들은 흔히 자바(Java) 코드 안에 String dbUrl = "jdbc:mysql://localhost:3306..." 처럼 값을 하드코딩(Hard-coding)하는 실수를 저지릅니다. 이렇게 코드를 짜면, 내 노트북(로컬)에서는 잘 돌던 프로그램이, IP가 완전히 다른 실제 라이브 운영(Production) 서버에 배포되는 순간 데이터베이스를 찾지 못하고 펑 터져버립니다. 배포할 때마다 소스코드를 열어서 주석 처리하고 IP를 고쳐서 빌드하실 건가요? 이런 원시적인 작업을 우아하게.. [Spring Boot] Spring Boot MVC 패턴 완벽 해부: Controller, Service, Repository의 분업 만약 여러분이 햄버거 매장의 점장이라고 상상해 봅시다. 카운터에서 손님의 주문(Request)을 받고 결제하는 직원이 있고, 뒤쪽 주방에서 패티를 굽고 햄버거를 조립(비즈니스 로직)하는 요리사가 있으며, 냉장고(Database)에서 신선한 식재료를 꺼내오는 창고 관리자가 있습니다. 이 세 명의 직원이 완벽하게 역할(Role)을 분담하여 일할 때 매장은 가장 효율적으로 돌아갑니다. 만약 카운터 직원이 주문을 받다 말고 주방에 들어가서 패티를 굽고 냉장고 문을 열어젖힌다면 매장은 금세 난장판이 될 것입니다. 스프링 부트(Spring Boot) 백엔드 애플리케이션도 이와 똑같습니다. 하나의 클래스 안에 모든 코드를 때려 넣는 '스파게티 코드'를 방지하고, 유지보수와 테스트를 극대화하기 위해 탄생한 아키텍처가 .. [Spring Boot] Spring Initializr: 완벽한 프로젝트 뼈대와 실무 의존성 설계 가이드 집을 지을 때 가장 중요한 것은 화려한 인테리어가 아니라 탄탄한 설계도와 뼈대(Foundation)입니다. 스프링 부트(Spring Boot) 개발 역시 마찬가지입니다. 처음에 프로젝트 뼈대를 어떻게 잡고, 빌드 도구를 무엇으로 선택하며, 어떤 라이브러리(Dependencies)들을 담고 시작하느냐에 따라 1년 뒤 프로젝트의 유지보수 난이도가 천차만별로 갈라집니다. 다행히도 스프링 진영은 개발자들이 손쉽게 뼈대를 짤 수 있도록 Spring Initializr(start.spring.io)라는 강력한 웹 기반의 제너레이터를 제공합니다.이번 시리즈의 두 번째 포스팅에서는 수많은 옵션들 앞에서 헤매는 주니어 개발자들을 위해, 실무에서 100% 통용되는 프로젝트 구조 설계와 필수 의존성(Dependencies).. [Spring Boot] 3.x 시작하기: 레거시 Spring과의 차이점과 완벽한 첫 세팅 자바(Java) 백엔드 생태계에서 Spring Framework는 절대적인 표준입니다. 수많은 엔터프라이즈 기업과 스타트업이 모두 스프링을 기반으로 거대한 서비스를 구축하고 있습니다. 그러나 과거의 레거시(Legacy) Spring은 초기 세팅이 너무나도 고통스러웠습니다. XML 파일에 빈(Bean)을 등록하고, 톰캣(Tomcat) 서버를 별도로 설치해서 .war 파일을 배포하고, 수십 개의 의존성 버전이 꼬이는 이른바 'XML 지옥(XML Hell)'과 '의존성 지옥(Dependency Hell)'을 겪어야만 했습니다. 이러한 고통을 완벽하게 해결하고 개발자가 오직 '비즈니스 로직(Business Logic)' 작성에만 집중할 수 있도록 혁신을 일으킨 구원자가 바로 Spring Boot(스프링 부트)입.. ← 이전 1 2 3 다음 →