[Basic-5] 싱글톤 컨테이너와 CGLIB의 동작 원리
·
Spring/Core
대부분의 스프링 애플리케이션은 웹 애플리케이션이다. 웹 환경은 수많은 고객이 동시에 요청을 보내는 특성을 가진다. 이러한 환경에서 스프링이 어떻게 수만 개의 객체 요청을 효율적으로 처리하는지 그 핵심 원리인 싱글톤 컨테이너에 대해 알아본다.1. 웹 애플리케이션과 싱글톤의 필요성 스프링 없는 순수한 DI 컨테이너인 AppConfig는 요청을 할 때마다 객체를 새로 생성한다. 만약 고객 트래픽이 초당 100회 발생한다면, 초당 100개의 서비스 객체가 생성되고 소멸되어야 한다. 이는 심각한 메모리 낭비를 초래한다. 이 문제를 해결하기 위해 해당 객체가 딱 1개만 생성되고, 이를 공유하도록 설계하는 것이 바로 싱글톤 패턴(Singleton Pattern)이다.2. 스프링 컨테이너: 싱글톤 레지스트리 직접 자..
[Basic-4] 스프링 컨테이너의 생성과 빈 관리 메커니즘
·
Spring/Core
지금까지는 개발자가 직접 AppConfig 객체를 생성하고 의존관계를 주입하였다. 이제부터는 스프링 프레임워크의 핵심인 스프링 컨테이너에 이 역할을 맡기는 방법을 알아본다.1. 스프링 컨테이너로의 전환순수 자바 기반의 AppConfig를 스프링 기반으로 변경하기 위해서는 두 가지 어노테이션이 필요하다.@Configuration: 해당 클래스를 설정을 구성하는 정보로 사용하겠다는 선언이다.@Bean: 메서드를 호출하여 반환된 객체를 스프링 컨테이너에 등록하라는 지시어이다.@Configurationpublic class AppConfig { @Bean public MemberService memberService() { return new MemberServiceImpl(memberR..
[Basic-3] 관심사의 분리와 의존관계 주입(DI)
·
Spring/Core
앞선 글에서 살펴본 것처럼, 구현 객체가 스스로 다른 구현 객체를 생성하고 연결하는 구조는 DIP와 OCP 원칙을 위반한다. 이 문제를 해결하기 위해 애플리케이션의 전체 동작 방식을 구성하고 객체 간의 관계를 설정하는 별도의 존재가 필요하다.1. 관심사의 분리 (Separation of Concerns) 애플리케이션을 하나의 공연이라고 가정해본다. 이전의 설계는 로미오 역할을 맡은 배우가 줄리엣 역할을 할 배우를 직접 초빙하는 것과 같았다. 즉, 배우가 연기라는 본연의 책임 외에 '상대 배우 캐스팅'이라는 과도한 책임까지 지고 있었던 것이다.배우: 자신의 배역을 수행하는 것에만 집중해야 한다. 어떤 상대 배우가 오더라도 똑같이 공연할 수 있어야 한다.공연 기획자: 공연을 구성하고, 담당 배우를 섭외하며,..
[Basic-2] 순수 자바 예제로 이해하는 DIP와 OCP 위반
·
Spring/Core
스프링의 필요성을 체감하기 위해, 스프링 프레임워크의 도움 없이 순수 자바(Pure Java)만으로 비즈니스 요구사항을 구현해 본다. 이 과정에서 다형성을 활용한 설계가 실제 운영 환경에서 어떤 한계에 부딪히는지 확인하는 것이 핵심이다.1. 비즈니스 요구사항과 설계우리가 구현할 시스템은 회원 가입, 조회 기능과 등급별 할인 정책을 포함한 주문 서비스이다.1.1. 회원 도메인 요구사항회원 등급: 일반(BASIC), VIP 두 가지 등급이 존재한다.데이터 저장: 자체 DB를 구축할 수도 있고, 외부 시스템과 연동할 수도 있다. (현재는 미확정 상태)1.2. 주문 및 할인 정책 요구사항할인 정책: 모든 VIP 등급 회원에게는 1,000원을 할인해 주는 '고정 금액 할인'을 적용한다.유연성 확보: 할인 정책은 ..
[Basic-1] 객체 지향 설계와 스프링의 탄생 배경
·
Spring/Core
스프링 프레임워크가 자바 엔터프라이즈 시장의 표준으로 자리 잡은 이유는 단순히 기능이 많아서가 아니다. 스프링의 본질은 '자바 언어가 가진 객체 지향의 특징을 극대화할 수 있도록 돕는 것'에 있다. 그 시작점인 자바 진영의 역사와 객체 지향 설계 원칙에 대해 정리한다.1. 자바 진영의 추운 겨울과 스프링의 탄생 스프링이 등장하기 전, 자바 엔터프라이즈 개발의 중심에는 EJB(Enterprise JavaBeans)가 있었다. EJB는 당시 기술적으로 권위 있는 표준이었으나, 다음과 같은 치명적인 단점이 존재했다.높은 복잡도와 의존성: EJB 표준을 따르기 위해 비즈니스 로직보다 프레임워크에 종속적인 코드를 더 많이 작성해야 했다.어려운 테스트: 프레임워크 없이는 단독으로 테스트하기가 매우 까다로웠다.비싼 ..
[Practice-3] Spring Core: 깔끔하고 확장성 있는 예외 처리
·
Spring/Core
1. 들어가며 웹 애플리케이션을 개발할 때 정상적인 성공 응답만큼이나 중요한 것이 에러 상황을 클라이언트에게 어떻게 전달할 것인가이다. Spring Boot를 사용하면 기본적으로 White Label Error Page 또는 단순한 에러 JSON이 내려가지만, 이는 프론트엔드나 모바일 클라이언트가 사용하기에는 정보가 부족하고 형식 또한 일관되지 않다. 특히 REST API 환경에서는 에러 응답 역시 하나의 계약(Contract) 이다. 어떤 에러가 발생하더라도 항상 동일한 구조의 JSON을 내려주어야 클라이언트는 예외 케이스를 예측 가능하게 처리할 수 있다. 본 글에서는 @RestControllerAdvice를 활용해 예외 처리를 중앙화하고, ErrorCode, BusinessException, Er..
[Practice-2] 객체 생성: 빌더 패턴과 정적 팩터리 메서드
·
Spring/Core
Spring(Java)으로 개발하다 보면 객체를 생성하는 다양한 방법을 마주하게 됩니다. 그중 가장 대표적인 것이 빌더 패턴(Builder Pattern)과 정적 팩터리 메서드(Static Factory Method)입니다. 많은 개발자들이 자연스럽게 "Entity에는 빌더 패턴, DTO에는 정적 팩터리 메서드"라는 규칙을 따르곤 합니다. 왜 이런 관행이 생겼을까요? 단순히 파라미터 개수 때문일까요? 이 글에서는 두 패턴의 핵심적인 차이와 각자의 역할에 가장 적합한 사용 기준을 명확하게 알아보겠습니다.빌더 패턴 (Builder Pattern): "어떻게(How) 만들 것인가?" 🧱빌더 패턴은 복잡한 객체를 생성할 때, 그 과정을 단계별로 명확하게 표현하는 데 중점을 둡니다. 여러 데이터를 '조립'하여 ..
[Practice-1] ResponseEntity<>
·
Spring/Core
1. 배경 지식Spring MVC로 API를 처음 만들 때의 기억은 아직도 생생하다. 컨트롤러 메서드에서 DTO 객체를 반환하기만 하면, Jackson 라이브러리가 마법처럼 JSON으로 변환해 주었다. 코드는 간결했고, 직관적이었다. 하지만 코드 리뷰 겸 다른 사람들이 올린 깃 레파지토리를 보면 단순히 DTO만 반환하지 않는다는것을 발견했다. 대부분의 코드는 DTO를 직접 반환하는 대신, 아래처럼 ResponseEntity라는 객체로 감싸서 반환하고 있었던 것이다. // 나의 코드 작성 방식@GetMapping("/members/{id}")public MemberDto getMember(@PathVariable Long id) { return memberService.findMember(id);}/..