스프링 애플리케이션에서 사용하는 서비스, 컨트롤러, 리포지토리... 모두 빈이라는 사실 알고계셨나요?
그래서 빈이 뭔데?? 🤔🤔

1. 스프링 빈이란 무엇인가
스프링에서 말하는 빈(Bean) 은 단순한 자바 객체가 아니라 스프링 컨테이너가 생성하고 관리하는 객체를 의미합니다.
중요한 점은 객체의 생성과 관리 책임이 개발자가 아니라 컨테이너에 있다는 것입니다.
개발자는 객체를 new로 직접 생성하지 않고 스프링이 대신 객체를 만들고, 필요할 때 주입해 줍니다.
이 방식의 핵심은 다음과 같습니다.
- 객체 생성 코드가 애플리케이션 전반에 흩어지지 않는다
- 구현체 변경에 유연해진다
- 테스트와 확장이 쉬워진다
이처럼 제어의 흐름이 개발자에서 프레임워크로 넘어가는 것을 IoC(Inversion of Control)라고 합니다.
2. 컴포넌트 스캔이란?
스프링은 애플리케이션 시작 시 @Component가 붙은 클래스를 자동으로 찾아 빈으로 등록합니다.
이 과정을 컴포넌트 스캔(Component Scan) 이라고 합니다.
컴포넌트 스캔 덕분에 다음과 같은 작업이 필요 없어졌습니다.
- 설정 파일에 @Bean을 하나씩 등록
- 객체 생성과 관리 로직을 직접 작성
즉, “빈으로 등록할 대상을 찾아오는 역할”을 스프링이 대신 수행합니다.
3. @Component와 기본 스캔 대상
@Component의 역할
@Component public class MemberServiceImpl { }
@Component는 “이 클래스는 스프링이 관리해야 할 대상이다”라고 스프링에 알려주는 표시입니다.
컴포넌트 스캔은 이 애노테이션을 기준으로 동작합니다.
기본 스캔 대상 애노테이션
다음 애노테이션들은 내부적으로 @Component를 포함합니다.
- @Controller : 웹 요청 처리
- @Service : 비즈니스 로직
- @Repository : 데이터 접근 계층
- @Configuration : 설정 정보
기능은 같지만, 의미를 명확히 드러내기 위해 구분해서 사용합니다.
또한 스프링은 애노테이션에 따라 추가 동작을 수행하기도 합니다.
예를 들어 @Repository는 예외 변환 기능을 제공합니다.
예외 변환 기능?? 그게뭔데요?
“DB에서 터지는 제각각인 에러를, 스프링이 ‘표준 에러’로 번역해서 서비스까지 올려준다.”
왜 “번역”이 필요하냐
DB 관련 에러는 상황은 비슷해도, 기술/DB에 따라 에러 모양이 다릅니다.
- JDBC 쓰면 SQLException
- JPA(Hibernate) 쓰면 PersistenceException
- DB가 MySQL인지 Postgres인지에 따라서도 메시지/타입이 달라질 수 있음
이러면 서비스 코드에서 예외 처리하려고 할 때,
“지금은 MySQL 예외”, “지금은 Hibernate 예외” 이런 식으로 지저분하게 기술에 묶입니다.
@Repository가 해주는 일
@Repository가 붙은 클래스에서 DB 작업하다가 예외가 터지면, 스프링이 중간에서 이렇게 바꿉니다.
- “DB/기술마다 다른 예외” → “스프링 공통 예외(DataAccessException 계열)”
즉, 서비스 입장에서는 항상 스프링 예외로만 받게 됩니다.
한 가지 예시
“중복 저장” 상황을 생각해볼게요.
- 테이블에 email이 UNIQUE인데 똑같은 이메일을 또 저장하려 함
원래는 DB마다 다른 예외가 터질 수 있는데, 스프링이 번역하면 보통 이런 식으로 올라옵니다.
- DuplicateKeyException (중복 키 예외)→ “아 중복 저장이구나” 를 서비스에서 쉽게 알 수 있음!
4. 빈 이름 생성 규칙
컴포넌트 스캔으로 등록된 빈은 이름을 가집니다.
기본 전략
- 클래스 이름의 첫 글자를 소문자로 변환
MemberServiceImpl → memberServiceImpl
수동 지정
@Component("memberService")
빈 이름을 직접 지정할 수도 있습니다.
다만 특별한 이유가 없다면 기본 전략을 따르는 것이 일반적입니다.
5. 자동 빈 등록 과정 한 번에 정리
컴포넌트 스캔과 자동 의존관계 주입 과정은 다음 순서로 진행됩니다.
- 스프링 컨테이너가 @Component가 붙은 클래스를 탐색
- 해당 클래스를 스프링 빈으로 등록
- 의존관계 주입 대상에 @Autowired가 있다면
- 등록된 빈 중에서 타입에 맞는 객체를 찾아 주입
이는 내부적으로 getBean(타입)을 호출하는 것과 같은 동작이라고 볼 수 있습니다.
6. 탐색 위치와 basePackages 전략
컴포넌트 스캔은 기본적으로 애플리케이션 시작 위치를 기준으로 동작합니다.
보통 @SpringBootApplication이 선언된 클래스의 패키지를 루트로 삼아
그 하위 패키지를 전부 스캔합니다.
이 방식이 권장되는 이유는 명확합니다.
- 스캔 범위가 자연스럽다
- 설정이 단순하다
- 의도치 않은 빈 등록을 방지할 수 있다
그래서 대부분의 경우 basePackages를 별도로 지정하지 않습니다.
7. 자동 등록 vs 수동 등록
자동 등록이 적합한 경우
- 컨트롤러, 서비스, 리포지토리
- 일반적인 비즈니스 로직
- 역할이 명확한 클래스
수동 등록을 고민해볼 경우
- 기술 지원 객체
- 구현체 교체 가능성이 높은 전략 클래스
- 다형성을 적극 활용하는 경우
핵심 기준은 단순합니다.
“이 빈의 선택 기준과 의도가 코드에서 명확히 드러나는가?”
요약
- 스프링 빈은 컨테이너가 생성하고 관리하는 객체
- 컴포넌트 스캔은 빈을 자동으로 수집하는 메커니즘
- @Component 계열 애노테이션을 기준으로 등록된다
- 빈 이름은 기본 규칙이 있으며 필요하면 수동 지정 가능
- 자동 등록은 기본 전략이고, 수동 등록은 선택 사항이다
다음 글에서는 이렇게 등록된 빈들이 언제, 어떻게 의존관계를 주입받는지를 알아보겠습니다~!!
'스프링 > 개념' 카테고리의 다른 글
| [빈 시리즈-2] 스프링은 언제 의존관계를 주입하는가 (0) | 2026.01.12 |
|---|---|
| 싱글톤 패턴의 한계와 싱글톤 컨테이너 (1) | 2026.01.08 |
| 커서 기반 페이징(Cursor-based Pagination) (0) | 2025.05.25 |