게으른 개발자의 끄적거림

Java 스프링 어노테이션이란? (개념 및 정리)

끄적잉 2024. 12. 4. 21:58

Java Spring 프레임워크에서 사용되는 **어노테이션(Annotation)**은 개발자가 간결하고 직관적으로 애플리케이션을 구성할 수 있도록 도와줍니다. Spring 어노테이션은 코드와 구성 파일의 양을 줄이고, 코드의 가독성을 높이며, 설정을 명확하게 지정하는 데 중요한 역할을 합니다. 이 문서에서는 **Spring 어노테이션의 개념, 주요 어노테이션의 종류와 사용법, 그리고 실용적인 예제**를 중심으로 상세히 설명하겠습니다.

---


## 1. Spring 어노테이션의 개념

Spring 어노테이션은 클래스, 메서드, 필드, 매개변수 등에 **메타데이터**를 제공하여 Spring 컨테이너가 해당 요소를 관리하거나 동작을 변경할 수 있도록 하는 마크업 도구입니다.  
과거 Spring XML 기반 설정을 주로 사용했으나, 현재는 어노테이션을 통해 설정과 정의를 더욱 간단하고 직관적으로 처리합니다.

### 1.1 어노테이션의 주요 특징
- **선언적 프로그래밍**: 어노테이션을 통해 명시적으로 동작을 지정할 수 있습니다.
- **설정 간소화**: XML 구성 파일의 대체제로 사용되며, Java Config와 함께 사용 가능합니다.
- **유지보수성 향상**: 관련 설정이 코드에 포함되어 가독성과 유지보수성이 높아집니다.

---

 


## 2. 주요 Spring 어노테이션

Spring 어노테이션은 크게 **컴포넌트 스캔 및 빈 정의**, **의존성 주입**, **AOP(Aspect-Oriented Programming)**, **웹 계층** 등으로 나뉩니다.


### 2.1 컴포넌트 스캔 및 빈(Bean) 정의 관련 어노테이션

#### 2.1.1 `@Component`
- **설명**: Spring 컨테이너가 해당 클래스를 빈(Bean)으로 등록하도록 지정합니다.
- **사용 위치**: 클래스
- **예제**:
  ```java
  @Component
  public class MyService {
      public void serve() {
          System.out.println("Service is working!");
      }
  }
  ```

#### 2.1.2 `@Repository`
- **설명**: 데이터 액세스 계층(DAO)을 정의하며, 데이터베이스와 관련된 예외를 Spring 예외로 변환합니다.
- **사용 위치**: 클래스
- **예제**:
  ```java
  @Repository
  public class UserRepository {
      public void save(User user) {
          // 데이터 저장 로직
      }
  }
  ```

#### 2.1.3 `@Service`
- **설명**: 비즈니스 로직 계층에서 사용되는 빈으로 표시합니다.
- **사용 위치**: 클래스
- **예제**:
  ```java
  @Service
  public class UserService {
      public void processUser(User user) {
          // 비즈니스 로직
      }
  }
  ```

#### 2.1.4 `@Controller`
- **설명**: MVC 아키텍처에서 컨트롤러로 작동하며, HTTP 요청을 처리합니다.
- **사용 위치**: 클래스
- **예제**:
  ```java
  @Controller
  public class HomeController {
      @RequestMapping("/")
      public String home() {
          return "home";
      }
  }
  ```


---

### 2.2 의존성 주입(Dependency Injection) 관련 어노테이션

#### 2.2.1 `@Autowired`
- **설명**: Spring 컨테이너에서 자동으로 의존성을 주입합니다.
- **사용 위치**: 생성자, 필드, 메서드
- **예제**:
  ```java
  @Component
  public class OrderService {
      @Autowired
      private UserRepository userRepository;

      public void createOrder() {
          userRepository.save(new User());
      }
  }
  ```

#### 2.2.2 `@Qualifier`
- **설명**: 동일한 타입의 빈이 여러 개 있을 때 특정 빈을 선택하도록 지정합니다.
- **사용 위치**: 필드, 메서드 파라미터
- **예제**:
  ```java
  @Component("specificRepository")
  public class SpecificUserRepository implements UserRepository {}

  @Component
  public class OrderService {
      @Autowired
      @Qualifier("specificRepository")
      private UserRepository userRepository;
  }
  ```


#### 2.2.3 `@Primary`
- **설명**: 동일한 타입의 빈 중 기본 빈으로 우선순위를 지정합니다.
- **사용 위치**: 클래스
- **예제**:
  ```java
  @Primary
  @Component
  public class DefaultUserRepository implements UserRepository {}
  ```

---

### 2.3 설정 관련 어노테이션

#### 2.3.1 `@Configuration`
- **설명**: Spring 설정 클래스임을 나타냅니다. 내부에서 빈을 정의합니다.
- **사용 위치**: 클래스
- **예제**:
  ```java
  @Configuration
  public class AppConfig {
      @Bean
      public UserService userService() {
          return new UserService();
      }
  }
  ```

#### 2.3.2 `@Bean`
- **설명**: 개발자가 직접 빈을 정의할 때 사용합니다.
- **사용 위치**: 메서드
- **예제**:
  ```java
  @Bean
  public OrderService orderService() {
      return new OrderService();
  }
  ```


---

### 2.4 AOP(Aspect-Oriented Programming) 관련 어노테이션

#### 2.4.1 `@Aspect`
- **설명**: 클래스가 AOP의 애스펙트(Aspect)임을 나타냅니다.
- **사용 위치**: 클래스
- **예제**:
  ```java
  @Aspect
  @Component
  public class LoggingAspect {
      @Before("execution(* com.example..*(..))")
      public void logBefore(JoinPoint joinPoint) {
          System.out.println("Method called: " + joinPoint.getSignature());
      }
  }
  ```

#### 2.4.2 `@Before`, `@After`, `@Around`
- **설명**: 특정 메서드 호출 전후에 실행할 동작을 정의합니다.
- **예제**:
  ```java
  @Around("execution(* com.example..*(..))")
  public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
      System.out.println("Before method execution");
      Object result = joinPoint.proceed();
      System.out.println("After method execution");
      return result;
  }
  ```


---

### 2.5 웹 계층 관련 어노테이션

#### 2.5.1 `@RequestMapping`
- **설명**: HTTP 요청 URL과 컨트롤러 메서드를 매핑합니다.
- **사용 위치**: 클래스, 메서드
- **예제**:
  ```java
  @Controller
  @RequestMapping("/users")
  public class UserController {
      @RequestMapping("/create")
      public String createUser() {
          return "createUser";
      }
  }
  ```

#### 2.5.2 `@RestController`
- **설명**: 컨트롤러와 `@ResponseBody`를 결합하여 JSON 형식으로 응답합니다.
- **사용 위치**: 클래스
- **예제**:
  ```java
  @RestController
  public class ApiController {
      @GetMapping("/api/data")
      public List<String> getData() {
          return Arrays.asList("Data1", "Data2");
      }
  }
  ```

#### 2.5.3 `@GetMapping`, `@PostMapping`, `@PutMapping`, `@DeleteMapping`
- **설명**: HTTP 메서드별 매핑을 제공합니다.
- **예제**:
  ```java
  @GetMapping("/users")
  public List<User> getUsers() {
      return userService.getAllUsers();
  }
  ```

---



### 2.6 트랜잭션 관련 어노테이션

#### 2.6.1 `@Transactional`
- **설명**: 메서드나 클래스에 트랜잭션 관리를 적용합니다.
- **사용 위치**: 클래스, 메서드
- **예제**:
  ```java
  @Service
  public class OrderService {
      @Transactional
      public void placeOrder(Order order) {
          // 트랜잭션 관리 하에 실행
      }
  }
  ```

---

## 3. 어노테이션 사용의 장점
1. **코드 간소화**: XML 기반 설정보다 직관적이고 간결합니다.
2. **자동화**: Spring 컨테이너가 자동으로 객체를 관리하므로 개발자가 직접 관리할 필요가 줄어듭니다.
3. **가독성 향상**: 어노테이션만으로 동작과 설정을 이해할 수 있습니다.
4. **유지보수 용이**: 설정이 코드에 포함되어 있어 수정이 쉽습니다.