📌 @Component : 모든 것의 시작


스프링에게 "이 클래스를 Bean으로 등록해줘"라고 알려주는 가장 기본적인 어노테이션

@Component
public class MyUtil {
    public String formatDate(LocalDate date) {
        return date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }
}

@Component를 붙이면 스프링이 앱을 시작할 때 이 클래스를 찾아서 객체를 만들고, 컨테이너에 Bean으로 보관한다. 이걸 컴포넌트 스캔(Component Scan)이라고 한다

✨ TIP : @SpringBootApplication 어노테이션 안에 @ComponentScan이 포함되어 있다. 그래서 메인 클래스가 있는 패키지와 그 하위 패키지에 있는 모든 @Component 클래스를 자동으로 찾는다

com.myname.board/
├── BoardApplication.java          ← @SpringBootApplication (여기서부터 스캔 시작)
├── controller/
│   └── PostController.java        ← ✅ 스캔됨
├── service/
│   └── PostService.java           ← ✅ 스캔됨
└── repository/
    └── PostRepository.java        ← ✅ 스캔됨

com.myname.other/
└── SomeClass.java                 ← ❌ 다른 패키지라서 스캔 안 됨

이것 때문에 프로젝트의 모든 코드는 반드시 메인 클래스와 같은 패키지 또는 하위 패키지에 있어야 한다

✅ @Controller, @Service, @Repository : @Component의 자식


사실 이 세 어노테이션은 전부 @Component를 포함하고 있다. 소스 코드를 까보면:

image.png

// 실제 스프링 소스 코드 (간략화)
@Component
public @interface Service { }

@Component
public @interface Repository { }

@Component
public @interface Controller { }

그러면 전부 @Component를 쓰면 되지, 왜 굳이 나눠놨을까? (2가지 이유 존재)

➡️ 이유 1: 역할을 명확하게 표현

코드를 읽는 사람이 이 클래스가 어떤 역할인지 바로 알 수 있다

@Controller   → "아, 이건 웹 요청을 받는 클래스구나"
@Service      → "아, 이건 비즈니스 로직을 처리하는 클래스구나"
@Repository   → "아, 이건 DB와 통신하는 클래스구나"

➡️ 이유 2: 스프링이 추가 기능을 제공

각 어노테이션은 @Component 이상의 일을 한다:


✅ 각 어노테이션을 사용법

3계층 아키텍처와 매핑하면 이렇다:

[클라이언트 요청]
      ↓
┌─────────────────────┐
│   @RestController   │  ← 요청을 받고, 응답을 반환
│   PostController    │     URL 매핑, 요청 데이터 추출
└─────────┬───────────┘
          ↓
┌─────────────────────┐
│      @Service       │  ← 비즈니스 로직 처리
│     PostService     │     검증, 계산, 변환, 트랜잭션
└─────────┬───────────┘
          ↓
┌─────────────────────┐
│     @Repository     │  ← DB 접근
│    PostRepository   │     저장, 조회, 수정, 삭제
└─────────────────────┘