어노테이션 설정 스테레오타입 컴포넌트 스캔 @Autowired @Configuration 📝 문제풀이
◀ 이전 📋 목차 CH 05 ▶
🏷️ CHAPTER 04 · 입문

어노테이션 하나로 빈이 등록된다

예전엔 XML 파일에 빈을 하나하나 적었어요. 요즘은 클래스에 어노테이션(@) 한 줄만 붙이면 스프링이 알아서 빈으로 등록해줘요. 이번 장은 @Component 계열과 컴포넌트 스캔이 핵심입니다.

🎯 이 장을 끝내면
🏷️
어노테이션 설정
XML 대신 어노테이션(@)으로
빈 등록 방식이 훨씬 간단해졌어요.

CH 03에서 배웠듯이, 스프링은 빈(Bean)을 컨테이너에 등록해두고 관리해요. 그런데 "어떤 클래스를 빈으로 등록할지"를 스프링에게 알려주는 방법이 필요하죠.

🏷️ 번외편 — 스프링 애너테이션 총정리 (컴포넌트 등록·주입·웹/REST·JPA·검증·보안까지 한곳에) 새 탭 ↗
🔤
빈(Bean) — 스프링이 대신 만들어 컨테이너에 담아 관리하는 객체예요. 개발자가 직접 new 하지 않고 스프링에게 맡긴 "부품"이라고 생각하면 돼요. (CH 03에서 다뤘어요.)
📜 예전 방식 — XML 설정 예전에는 applicationContext.xml 같은 파일에 빈을 하나하나 손으로 등록했어요. 클래스가 많아지면 XML도 길어지고 관리가 번거로웠어요.
<!-- 예전 XML 방식 (참고용) -->
<bean id="memberService" class="com.study.MemberService">
    <constructor-arg ref="memberRepository"/>
</bean>
<bean id="memberRepository" class="com.study.MemberRepository"/>
🏷️ 요즘 방식 — 어노테이션(@) 이제는 클래스 위에 어노테이션(@)을 한 줄 붙이기만 하면 돼요. 스프링이 그 표시를 보고 알아서 빈으로 등록해줘요. XML을 열 필요가 없어졌어요.
@Service                 // ← 이 한 줄이면 빈 등록 끝!
public class MemberService {
    // ...
}
💡 어노테이션(Annotation)은 코드에 붙이는 "메타 정보 표시"예요. 스프링은 이 표시를 읽어서 "아, 이 클래스는 빈으로 만들어야겠구나"라고 판단해요.
🔤
어노테이션(Annotation) — 코드에 붙이는 "스티커 메모"예요. 클래스나 메서드 위에 @이름 형태로 딱 붙여서 "이건 이런 용도야"라고 표시만 해둬요. 그러면 스프링이 실행할 때 이 스티커들을 하나하나 읽어보고 "아, 이 클래스는 빈으로 등록하라는 거구나" 하고 알아서 처리해줘요. 노트에 포스트잇을 붙여 표시해두는 것과 똑같답니다.
🧭
이번 장의 핵심. 어노테이션은 종류가 많아 보이지만, 대부분 @Component 하나의 변형이에요. 그 관계만 잡으면 전부 쉽게 이해됩니다.
🎭
스테레오타입
@Component와 그 역할별 별칭들
이름만 달라 보여도 뿌리는 하나예요.

스프링이 빈으로 등록할 클래스에 붙이는 대표 어노테이션이 @Component예요. 그런데 실무에서는 클래스가 어떤 역할(계층)을 하는지 드러내려고, @Component의 특수화된 별칭들을 씁니다.

🎭 스테레오타입(Stereotype) 어노테이션 @Controller, @Service, @Repository모두 내부적으로 @Component를 포함하고 있어요. 그래서 빈으로 등록되는 동작은 셋 다 똑같아요. 다만 이름을 달리 써서 그 클래스의 역할(의미)을 코드에서 바로 알 수 있게 해줘요. @Service를 @Component로 바꿔도 빈 등록은 동일하지만, "이건 비즈니스 로직 계층이다"라는 의미가 사라져요. 그래서 역할에 맞는 어노테이션을 쓰는 게 좋아요.
🔤
스테레오타입(Stereotype) — 클래스의 역할·유형을 한눈에 드러내는 "표준 이름표"를 뜻해요. @Controller·@Service·@Repository가 여기에 해당해요.
어노테이션담당 계층 / 역할
@Component가장 일반적인 빈. 특정 계층에 속하지 않는 공용 컴포넌트에 사용.
@Controller웹 요청 처리 계층. 사용자의 요청을 받아 응답을 돌려줌.
@Service비즈니스 로직 계층. 핵심 업무 처리를 담당.
@RepositoryDB 접근(데이터) 계층. 데이터베이스와의 저장·조회를 담당.
@Component @Controller @Service @Repository 스테레오타입 계층
💡
왜 굳이 나눠 쓸까? @Repository는 DB 예외를 스프링 예외로 바꿔주는 등 계층별 추가 기능이 붙기도 해요. 하지만 입문 단계에서는 "역할을 드러내는 @Component의 별칭"으로 기억하면 충분해요.
🔍
컴포넌트 스캔
스프링이 알아서 훑어서 등록해요
어노테이션을 실제로 "찾아내는" 과정이에요.

클래스에 @Component 계열을 붙였다고 자동으로 등록되는 건 아니에요. 스프링이 지정된 패키지를 훑으며(scan) 그 어노테이션이 붙은 클래스를 찾아서 빈으로 등록하는데, 이 과정을 컴포넌트 스캔(Component Scan)이라 해요.

🔤
컴포넌트 스캔(Component Scan) — 스프링이 지정된 패키지 안의 클래스들을 쭉 훑어보며 @Component 계열 스티커가 붙은 것만 골라 빈으로 등록하는 과정이에요. 선생님이 교실을 돌면서 이름표를 단 학생만 출석부에 적어 넣는 것과 비슷해요. 우리는 클래스에 "표시(어노테이션)"만 해두면, 실제로 찾아 등록하는 일은 스프링이 알아서 해줘요.
🏷️
@Component 부착
클래스에 표시만
🔍
컴포넌트 스캔
패키지를 훑어 자동 탐지
🍃
빈 자동 등록
컨테이너에 담김
🚀 스캔은 누가 시작할까? 스프링 부트에서는 @SpringBootApplication이 붙은 메인 클래스가 컴포넌트 스캔의 출발점이에요. 이 어노테이션 안에 스캔 기능이 포함돼 있어서, 메인 클래스가 있는 패키지와 그 하위 패키지를 자동으로 훑어요.
@SpringBootApplication   // 이 위치를 기준으로 하위 패키지를 스캔
public class StudyApplication {
    public static void main(String[] args) {
        SpringApplication.run(StudyApplication.class, args);
    }
}
그래서 보통 메인 클래스를 최상위 패키지에 두고, 나머지 컨트롤러·서비스·리포지토리를 그 하위에 배치해요. (@SpringBootApplication은 CH 05에서 자세히!)
💉
@Autowired
필요한 빈을 자동으로 주입
CH 02의 DI를 어노테이션으로 실현해요.

빈을 등록했으면, 이제 서로 연결(주입)해야죠. 이때 쓰는 게 @Autowired예요. 필요한 빈을 스프링이 컨테이너에서 찾아 자동으로 넣어줘요. (CH 02에서 배운 DI가 실제 코드로 나타난 거예요.)

🔤
@Autowired — "필요한 부품을 자동으로(auto) 연결(wire)해줘"라는 표시예요. 내가 직접 new로 만들어 넣지 않아도, 스프링이 컨테이너에 등록된 빈 중 딱 맞는 것을 찾아 끼워줘요. 가구 조립 설명서에 "여기엔 A부품을 꽂으세요"라고 적어두면 조립 담당자가 창고에서 A부품을 찾아 대신 꽂아주는 것과 같아요.
🙋
필요하다고 선언
생성자에 @Autowired
🔎
컨테이너에서 검색
같은 타입의 빈을 찾아요
🔌
자동으로 끼워줌
직접 new 안 해요
💉 @Autowired로 자동 주입 아래에서 MemberServiceMemberRepository가 필요해요. @Autowired를 붙이면 스프링이 등록된 MemberRepository 빈을 찾아 자동으로 주입해줘요. 직접 new 하지 않아요.
@Service
public class MemberService {

    private final MemberRepository memberRepository;

    @Autowired   // MemberRepository 빈을 자동 주입
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
}
💡 생성자가 하나뿐이면 @Autowired를 생략해도 스프링이 자동으로 주입해줘요. 요즘은 생성자 주입을 권장해요.
⚙️
@Configuration
자바 코드로 빈을 직접 등록하기
@Configuration + @Bean으로 수동 등록해요.

컴포넌트 스캔은 내가 만든 클래스를 자동 등록하는 데 좋아요. 그런데 외부 라이브러리 객체처럼 내가 어노테이션을 붙일 수 없는 경우엔 어떻게 할까요? 이럴 때 자바 설정 클래스(XML 대신 자바 코드로 빈을 등록하는 설정 클래스예요)로 직접(수동) 등록해요.

🔤
@Configuration · @Bean — @Configuration은 "이 클래스는 빈을 등록하는 설정서예요"라는 표시이고, @Bean은 그 설정서 안의 메서드에 붙여 "이 메서드가 만들어서 돌려주는 객체를 빈으로 등록해줘"라는 표시예요. 컴포넌트 스캔이 "이름표 붙은 걸 자동으로 주워 담는" 방식이라면, 이건 개발자가 직접 손으로 하나하나 등록하는 방식이라고 보면 돼요.
💡
왜 외부 객체는 수동으로? 외부 라이브러리 클래스는 남이 만든 코드라 내가 그 위에 @Component를 붙일 수가 없어요(파일을 고칠 수 없으니까요). 그래서 내 설정 클래스에서 @Bean 메서드로 "이 객체를 빈으로 등록해줘"라고 대신 등록해주는 거예요.
🤖
자동 등록
내가 만든 클래스
@Component 계열 + 컴포넌트 스캔
🔧
수동 등록
외부 객체·세밀한 설정
@Configuration + @Bean
⚙️ @Configuration + @Bean 클래스에 @Configuration을 붙이면 설정 클래스가 돼요. 그 안의 메서드에 @Bean을 붙이면, 그 메서드가 반환하는 객체가 빈으로 등록돼요. 개발자가 직접 생성 로직을 작성하므로 세밀한 제어가 가능해요.
@Configuration                 // 설정 클래스
public class AppConfig {

    @Bean                      // 반환 객체를 빈으로 등록
    public MemberRepository memberRepository() {
        return new MemberRepository();
    }

    @Bean
    public MemberService memberService() {
        // 위의 memberRepository() 빈을 주입해 등록
        return new MemberService(memberRepository());
    }
}
💡 정리하면 — 내 클래스는 @Component 계열 + 컴포넌트 스캔으로 자동, 외부 객체나 세밀한 설정은 @Configuration + @Bean으로 수동 등록해요.
🔧
@Bean메서드에 붙고, @Component클래스에 붙어요. 둘 다 결과적으로 빈을 등록하지만, 붙는 위치와 등록 방식(수동/자동)이 달라요.
🔤
자바 기반 설정 vs XML 설정 — 예전엔 빈 정보를 XML 파일에 적었지만, 요즘은 @Configuration 클래스처럼 자바 코드로 적어요. 자바로 적으면 오타가 나도 컴파일 단계에서 바로 걸리고, IDE의 자동완성 도움도 받을 수 있어 더 안전하고 편해요. (똑같은 "빈 등록"을 XML로 쓰느냐 자바로 쓰느냐의 차이일 뿐이에요.)
🧠 이 장 핵심 요약
📝
문제풀이 · 점검
배운 걸 가볍게 점검해봐요
시험이 아니라 "내가 이해했나" 확인용이에요. 틀려도 바로 해설이 나와요.
🧪
문제를 풀면 즉시 정답과 해설이 나오고, 위쪽 바에 점수가 쌓여요. 네 가지 유형(객관식 · O/X · 빈칸 · 개념)을 섞어 두었어요.
CH 05 🚀 Spring Boot 개요 — 설정 자동화의 마법과 @SpringBootApplication