<aside> 1️⃣ Annotation의 개념
</aside>
<aside> 2️⃣ 주로 사용하는 어노테이션
</aside>
@Component:
@Component("beanName")
**과 같은 방식으로 사용할 수 있다.@Service, @Repository, @Controller:
@Component
**의 특별한 형태이며, 스프링 MVC에서의 계층 구조를 나타낸다. **@Service
**는 서비스 계층, **@Repository
**는 데이터 액세스 계층, **@Controller
**는 프레젠테이션(웹) 계층을 나타낸다.@Autowired:
@Autowired
**가 붙은 곳에 스프링은 해당 타입의 빈을 찾아 주입한다.@RequestMapping, @GetMapping, @PostMapping, @PutMapping, @DeleteMapping:
@RequestMapping
**은 기본적인 매핑 어노테이션이며, HTTP 메서드 타입을 지정하지 않으면 모든 HTTP 요청을 처리한다.
나머지는 각각의 HTTP 메서드에 해당하는 요청만 처리한다.@PathVariable:
@PathVariable
어노테이션은 HTTP 요청의 URL 경로에 있는 값을 메서드의 매개변수로 바인딩해준다. 예를 들어, **@GetMapping("/users/{id}")
**과 같은 메서드가 있고, **@PathVariable Long id
**라는 매개변수(파라미터)가 있다면, /users/123 요청에서 123이 long타입을 가진 id 매개변수(파라미터)에 바인딩됩니다. 이걸 가지고 메서드 내부에서 사용하면 된다.@RequestParam:
@RequestParam
어노테이션은 HTTP 요청의 쿼리 매개변수를 메서드의 매개변수로 바인딩한다. 예를 들어, **@RequestParam String name
**이라는 매개변수가 있으면, /path?name=value 요청에서 value가 name 매개변수에 바인딩 된다. → 쉽게 설명하면 jsp에서 input 태그에 필요한 내용을 넣고 form을 submit하면 그 input 태그에 설정해준 name과 value가 url에 쿼리스트링으로 ?name=value이렇게 getMapping이 넘어오는데 여기서 넘긴 값인 value가 @RequestParam String name
에서 name에 바인딩된다. 그럼 이 바인딩된 값을 가져다 메서드에 사용하면 된다.HttpServletRequest request
)**이렇게 메서드 파라미터에 선언한 다음 메서드 내부에서 request.getParam(””)
이렇게해서 쿼리스트링으로 보낸 파라미터 값을 꺼내는것보다 @RequestParam이 훨씬 더 가독성도 좋고 효율적이고 좋다고 한다. → 타입변환도 해주고 바인딩된값이 필요한지도 설정가능하고 바인딩된값이 없을때 기본값을 설정해줄수도 있다.// 클라이언트가 /search라는 URL로 검색어(keyword=Spring)를 담아서 전송했다.
<http://localhost:8080/search?keyword=Spring>
// 이 요청을 처리하는 컨트롤러 메서드
@GetMapping("/search")
public String search(@RequestParam(value = "keyword", defaultValue = "spring") String keyword, Model model) {
model.addAttribute("keyword", keyword);
return "searchResult";
}
@RequestParam("keyword")
**은 HTTP 요청의 **keyword
**라는 이름의 파라미터를 메서드의 keyword
매개변수에 바인딩한다. 즉, 사용자가 검색창에 "Spring"이라고 입력하면 keyword
매개변수에 "Spring"이라는 값이 들어가게 된다. 또한, **@RequestParam
**에는 선택적으로 defaultValue
속성을 지정할 수 있다. 이는 해당 파라미터가 없을 경우에 사용될 기본값을 지정한다.
keyword
파라미터가 요청에 없을 경우 기본값으로 "spring"이 keyword
매개변수에 설정된다.@ResponseBody, @RestController:
@ResponseBody
**는 메서드 레벨에서 사용되며, **@RestController
**는 클래스 레벨에서 사용되며, 해당 컨트롤러의 모든 메서드에 **@ResponseBody
**가 적용된 것과 같은 효과를 준다.@ResponseBody
는 예를 들어, JSON을 반환하는 RESTful API를 만드는 경우에 주로 사용한다. 만약 json받는데 이 어노테이션을 안달면 오류난다.@ModelAttribute:
// 사용자는 form에 아래의 값들을 입력해서 보낸다고 가정한다.
First Name: John
Last Name: Doe
Email: [email protected]
// 이 form 데이터를 받아서 처리할 객체는 다음과 같다.
public class User {
private String firstName;
private String lastName;
private String email;
// getter and setter methods...
}
// form 데이터를 받아서 이를 User객체에 바인딩하는 컨트롤러 메서드
@PostMapping("/signup")
public String signup(@ModelAttribute User user) {
// process the user
return "success";
}
@ModelAttribute
어노테이션은 HTTP 요청의 매개변수(여기서는 폼 데이터)를 User
객체로 변환하고, 이를 메서드의 매개변수로 바인딩한다.
폼의 입력 필드 이름과 User
클래스의 필드 이름이 일치하면, 스프링 MVC는 자동으로 해당 필드에 값을 설정한다.
이렇게 함으로써, 개발자는 HTTP 요청의 매개변수를 직접 파싱하거나 변환하는 수고를 덜 수 있다. 이런 기능은 스프링 MVC의 데이터 바인딩 기능 중 하나이다.@ModelAttribute
**는 컨트롤러 메서드의 실행 전에 특정한 메서드를 실행하도록 지정하는 용도로도 사용된다. 이런 경우에는 메서드 레벨에 **@ModelAttribute
**를 붙여 사용하며, 이 메서드는 컨트롤러 메서드가 실행되기 전에 먼저 실행되어 결과 값을 모델에 추가한다. 이는 주로 공통적으로 사용되는 참조 데이터를 뷰에 전달할 때 사용된다.@Bean:
@SpringBootApplication:
@Configuration
, @EnableAutoConfiguration
, **@ComponentScan
**을 결합하여 제공한다.@SpringBootApplication
어노테이션을 사용하면 스프링 부트 애플리케이션의 핵심 설정들을 한 번에 처리할 수 있다. 기본적으로 이 어노테이션을 붙인 클래스는 애플리케이션의 최상단에 위치하며, 이 클래스를 실행함으로써 스프링 부트 애플리케이션이 구동된다.@SpringBootApplication(scanBasePackages = {"com.example.myapp", "com.example.utils"})
public class Application {
// ...
}
com.example.myapp
패키지와 com.example.utils
패키지에서 컴포넌트를 찾는다.exclude
속성을 사용할 수 있다.@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class Application {
// ...
}
DataSourceAutoConfiguration
자동 구성을 사용하지 않도록 설정한다. 이는 예를 들어 데이터베이스가 없는 애플리케이션에서 데이터 소스 관련 자동 구성을 끄고자 할 때 사용할 수 있다.@Configuration:
@Bean
어노테이션이 붙은 메서드는 각각 하나의 빈 객체를 생성하고, 이를 스프링이 관리하는 애플리케이션 컨텍스트에 등록한다.@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
AppConfig
**라는 클래스는 **MyService
**라는 이름의 빈을 생성하는 설정을 포함하고 있다. 이 빈은 **AppConfig
**가 설정된 컨텍스트에서 MyService
타입의 빈이 필요할 때마다 사용된다.
스프링에서는 **@Configuration
이 붙은 클래스를 특별하게 처리하여, 해당 클래스의 @Bean
메서드가 반복적으로 호출되더라도 한 번 생성된 빈 객체를 재사용(singleton 범위를 가진 빈에 대해)**한다.
즉, AppConfig
클래스에서 myService()
메서드를 호출해도 항상 같은 MyService 인스턴스를 반환한다.@Configuration
클래스는 다른 @Configuration
클래스를 가져와서 사용할 수 있다.@Configuration
public class OtherConfig {
@Autowired
private AppConfig appConfig;
@Bean
public OtherService otherService() {
return new OtherServiceImpl(appConfig.myService());
}
}
OtherConfig
**는 **AppConfig
**의 **myService()
**를 호출하여 생성된 MyService
빈을 주입받아 OtherService
빈을 생성하는 데 사용한다.
이렇게 @Configuration
어노테이션을 사용하면, 각각의 @Bean
메서드가 각기 다른 빈 설정을 나타내며, 이 메서드들을 조합하여 전체 애플리케이션 설정을 구성할 수 있다.@SpringBootApplication
어노테이션을 사용하여 @Configuration
클래스를 자동으로 스캔한다.@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication
**은 애플리케이션의 메인 클래스가 있는 패키지를 기반으로 @Component
, @Service
, @Repository
, @Controller
, 그리고 @Configuration
등이 붙은 클래스를 자동으로 스캔하게 된다. 따라서 **@Configuration
**이 붙은 클래스는 **@SpringBootApplication
**이 붙은 메인 클래스와 같은 패키지 또는 하위 패키지에 위치해야 자동으로 인식된다.@Import
어노테이션을 사용하는 것은 이런 자동 스캔 범위 밖에 있는 @Configuration
클래스를 명시적으로 등록하고 싶을 때 사용한다.
예를 들어, @Configuration
클래스가 메인 클래스의 패키지 구조와 완전히 다른 곳에 위치해 있다면, **@Import
**를 사용해서 그 클래스를 불러와야 한다.@SpringBootApplication
@Import(ExternalConfig.class)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
ExternalConfig
클래스가 메인 애플리케이션 컨텍스트에 포함되게 된다.@SpringBootApplication
**과 **@Import(ExternalConfig.class)
**을 함께 사용할 경우, 기본적으로 자동 스캔 **@ComponentScan
**이 되어 빈으로 등록되는 클래스들에 추가로 **ExternalConfig.class
**에 있는 @Bean
정의도 등록이 된다. 즉, **ExternalConfig.class
**에서 **@Bean
**으로 등록해준 애들만 추가로 등록되는 것이지, 그 외의 **@Component
**로 등록한 애들이 빈으로 등록되지 않는 것은 아니다. @Component
등으로 등록한 빈들도 계속해서 등록되게 된다.@EnableAutoConfiguration: