티스토리 뷰
@Controller
Spring MVC에서 컨트롤러를 선언하는데 사용됩니다.
Spring Framework에서 해당 클래스를 컨트롤러로 인식하고, DispatcherServlet이 요청을 받으면
해당 컨트롤러를 호출한다. 이때, @RequestMapping을 사용하여 요청 URL과 컨트롤러 메서드를 매핑시킨다.
특징
- 해당 Annotation이 선언된 클래스는 Spring이 관리하는 Bean으로 등록됩니다.
- @RequestMapping이 선언된 메서드는 요청 URL과 매핑되며, 해당 URL로 요청이 들어오면 해당 메서드가 호출됩니다.
- 컨트롤러 메서드에서는 비즈니스 로직을 수행하고, 결과를 Model객체에 담아 View에 전달합니다.
- View는 결과를 사용자에게 출력하는 역할을 수행한다.
*비지니스 로직이란?
애플리케이션에서 실제로 수행하는 중요한 업무처리. 주로 Service계층에서 사용함
ex. 은행 어플리케이션 -> 계좌개설, 입금,출금,이체등 업무가 모두 비즈니스 로직
*왜 결과를 Model에 담는가?
- Controller와 View 사이의 데이터 전달이 편리 (View에서 Model 객체를 사용하여 데이터를 출력 가능)
- Model 객체를 사용하면 다양한 타입의 데이터를 전달가능
- Model 객체를 사용하면 View와의 결합도가 낮아짐
@Service
Spring에서 비즈니스 로직이 구현된 클래스를 선언하는데 사용됩니다.
@Service 사용하여 해당 클래스가 Service Layer에서 사용되는 클래스임을 나타내며,
Spring에서 해당 클래스를 자동으로 Bean으로 등록하여 사용할 수 있게 함.
-> Service Layer와 Repository Layer를 분리하여 각 계층은 독립적으로 개발,테스트,유지보수 함
* Service Layer
애플리케이션의 비즈니스 로직을 담당하는 계층으로 비즈니스 로직을 처리함.
Controller에서는 비즈니스 로직을 담당하지 않고 요청을 받고 응답을 반환하는 역할을 수행하며,
Service Layer에서는 비즈니스 로직을 처리하는 역할을 수행합니다.
*왜 Bean에 등록되어야 할까?
개발자들은 객체의 생성과 의존성 주입을 직접 관리하지 않고도, Spring 프레임워크가 객체를 자동으로 생성하고 주입하는 기능을 활용할 수 있다.
특징
- @Service을 사용하여 Service Layer를 구현하면, 해당 클래스를 자동으로 Bean으로 등록할 수 있습니다.
- 따라서, Controller에서 해당 클래스를 사용하려면 @Autowired을 사용하여 의존성 주입을 수행하면 됩니다.
- @Service은 @Component을 상속하고 있습니다. 따라서, @Service을 사용하면 해당 클래스는 Component로 등록되며, Spring Framework에서 Bean으로 관리됩니다.
- @Service은 Controller와 Repository Layer 사이에서 사용됩니다. Controller에서 요청을 받으면, Service Layer에서 비즈니스 로직을 수행하고, Repository Layer에서 데이터를 액세스하여 처리 결과를 반환합니다.
*자동으로 Bean으로 등록하면 뭐가 좋은가?
- 객체의 생성과 소멸을 Spring이 관리하기 때문에, 개발자가 객체의 생성과 소멸에 대한 로직을 작성하지 않아도 됩니다. 이로 인해 코드의 양이 줄어들고, 코드의 가독성과 유지보수성이 높아집니다.
- Bean으로 등록된 객체는 Spring의 IoC (Inversion of Control) 컨테이너에서 관리되기 때문에, 객체 간의 의존성 주입이 자동으로 이루어집니다. 이를 통해 객체 간의 결합도를 낮출 수 있으며, 유연한 애플리케이션을 만들 수 있습니다.
- Spring에서는 Bean으로 등록된 객체에 대해 다양한 기능을 제공합니다. 예를 들어, AOP (Aspect Oriented Programming)를 이용한 로깅, 트랜잭션 처리 등을 지원합니다. 이러한 기능을 사용하면 애플리케이션의 성능을 개선할 수 있습니다.
- Spring에서는 Bean으로 등록된 객체를 스코프에 따라 다르게 관리할 수 있습니다. 예를 들어, 요청마다 새로운 객체를 생성하는 Request Scope, 세션 단위로 객체를 관리하는 Session Scope 등이 있습니다. 이를 통해 애플리케이션의 메모리 사용량을 최적화할 수 있습니다.
- Spring에서는 Bean으로 등록된 객체에 대해 테스트 코드를 작성하기 쉽습니다. 스프링은 테스트에 필요한 Bean을 쉽게 만들 수 있도록 지원합니다. 이를 통해 테스트 코드의 작성과 유지보수가 용이해집니다.
@Autowired
Spring에서 자동으로 필요한 의존성을 주입하는데 사용됩니다.
@Autowired 사용하면, 해당 객체가 스프링 컨테이너에서 자동으로 생성되고,
의존하는 다른 객체를 자동으로 주입받음. -> 객체 간의 결합도를 낮추고, 유지보수성과 확장성을 높임
특징
- @Autowired을 필드에 선언하면, 해당 필드가 스프링 컨테이너에서 자동으로 생성된 빈과 연결됩니다.
- @Autowired을 Setter 메서드에 선언하면, 해당 Setter 메서드가 호출될 때 스프링 컨테이너에서 자동으로 생성된 빈이 해당 Setter 메서드로 주입됩니다.
- @Autowired을 생성자에 선언하면, 해당 생성자가 호출될 때 스프링 컨테이너에서 자동으로 생성된 빈이 해당 생성자로 주입됩니다.
- @Autowired을 사용하면, 스프링 컨테이너에서 객체를 생성하고, 의존성을 자동으로 주입해주므로, 개발자는 객체 생성 및 의존성 주입과 같은 부수적인 작업을 수동으로 처리하지 않아도 됩니다. 이를 통해, 코드의 가독성과 유지보수성을 향상시킬 수 있습니다.
*자동으로 생성된 빈과 연결된다란 뜻은?
스프링은 Bean을 생성하고, ApplicationContext에 등록한 후, 필요한 곳에서 해당 Bean을 가져다가 사용합니다.
스프링은 해당 필드의 타입에 해당하는 Bean을 ApplicationContext에서 찾아서, 필드에 주입합니다.
-> 스프링이 필요한 Bean을 자동으로 생성하고, 해당 Bean을 클래스의 필드에 주입함으로써, 개발자는 Bean을 생성하고 관리하는 코드를 작성하지 않아도 됩니다.
-> 이는 개발 시간을 단축시키고, 코드의 가독성을 높여주는 장점을 가지고 있습니다.
ex. MemberServiceImpl 클래스를MemberRepository와 의존성(Dependency)을 주입
*의존성을 자동으로 연결하는데 어떻게 객체 간의 결합도를 낮출까?
Spring Framework에서는 객체 간의 결합도를 낮추기 위해 Inversion of Control (IoC) 원칙을 적용
@Autowired 을 사용시
1. 스프링 컨테이너에서 객체 생성 및 관리를 담당하고, 객체 간의 의존성을 자동으로 주입
-> 코드의 가독성과 유지보수성 향상(개발자가 객체 생성과 의존성 주입에 대한 부수적인 작업을 수동으로 처리안하므로)
2. 객체 간의 의존성이 자동으로 연결되므로, 한 객체가 다른 객체에 직접적으로 의존X
-> 인터페이스나 추상 클래스를 통해 간접적으로 의존하도록 설계
-> 객체 간의 결합도를 낮춤
* 객체 간의 결합도
한 객체가 다른 객체에 의존하거나, 다른 객체의 내부 구조에 의존하게 되는 정도
* IoC
객체 생성과 관리를 컨테이너에게 위임하고, 객체 간의 의존성을 주입받도록 설계하는 방식
사용예시
public interface MemberService {
void register(Member member);
Member findById(Long memberId);
}
@Service //MemberServiceImpl 클래스를 Service Layer에 속하게 만듦
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository;
@Autowired //MemberRepository와 의존성(Dependency)을 주입
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Override
public void register(Member member) {
memberRepository.save(member);
}
@Override
public Member findById(Long memberId) {
return memberRepository.findById(memberId);
}
}
@Controller //MemberController 클래스를 Controller Layer에 속하게 만듦
public class MemberController {
private final MemberService memberService;
@Autowired
// MemberController 클래스를 MemberService와 의존성(Dependency)을 주입
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
@PostMapping("/members/new")
public String create(MemberForm form) {
Member member = new Member();
member.setName(form.getName());
memberService.register(member);
return "redirect:/members";
}
@GetMapping("/members/{id}")
public String detail(@PathVariable("id") Long memberId, Model model) {
Member member = memberService.findById(memberId);
model.addAttribute("member", member);
return "members/memberDetail";
}
}
@Repository
Spring에서 DAO를 구현하는 클래스를 선언하는데 사용됩니다.
데이터베이스와 관련된 역할을 수행하는 Repository Layer의 구현체임을 나타내기 위해 사용
@Autowired을 사용하여 Repository Layer와 Service Layer를 연결할 때 편리하다.
해당 클래스는 보통 데이터베이스와 직접적으로 연결되는 DAO(Data Access Object) 클래스를 구현함
* @Repository와 DAO와 관계
DAO 클래스를 Repository Layer에서 사용하게 되면, DAO 클래스의 메서드를 호출하여 데이터베이스와의 상호작용을 처리할 수 있다. 이때, Spring에서는 @Autowired 을 사용하여 Repository Layer에서 DAO 클래스를 주입할 수 있다. 이렇게 의존성 주입을 수행하면, 불필요한 코드 중복을 방지하고, 유지보수성과 생산성을 높일 수 있다.
@Component
Spring에서 빈으로 등록할 클래스를 선언하는데 사용됩니다.
@Component을 사용하여 클래스를 Bean으로 등록하고,
@Autowired을 사용하여 해당 Bean을 주입받아 사용하는 것이 일반적인 방법
*특징
@Controller, @Service, @Repository 은 @Component을 상속받는다.
@RequestMapping
Spring MVC에서 컨트롤러 클래스나 메서드에 URL을 매핑할 때 사용됩니다.
@Controller 어노테이션이 부착된 클래스 내부의 메서드들은 @RequestMapping 어노테이션을 사용하여 특정 URL 경로와 매핑된다.
* value : 매핑될 URL 경로를 지정, method : 해당 URL과 연결된 HTTP 요청 메서드를 지정
@Controller
public class HelloController {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello() {
return "hello";
}
}
*모든 메서드들의 URL 경로에 /users가 포함될경우
@Controller
@RequestMapping("/users")
public class UserController {
@RequestMapping("/{userId}")
public String getUser(@PathVariable("userId") Long userId, Model model) {
User user = userService.getUserById(userId);
model.addAttribute("user", user);
return "user";
}
}
@PathVariable
RESTful API에서 URL 경로에서 변수 값을 추출할 때 사용
*GET 요청이 들어왔을 때 @PathVariable을 사용하여 {id}에 해당하는 값을 Long id 매개변수로 받아온다.
-> URL 경로에서 변수 값을 추출 가능
@RestController
@RequestMapping("/users")
public class UserController {
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
// id에 해당하는 사용자 정보를 조회하는 로직
...
}
}
@RequestParam
Spring MVC에서 HTTP 요청 파라미터를 받아올 때 사용
@RequestParam Annotation을 붙이면 해당 파라미터의 값을 받아와서 매개변수에 할당해줌
*어노테이션 내의 "id", "name", "age" 값은 HTTP 요청에서 해당 파라미터 이름과 일치해야 한다. ex. id ->id
GET /users?id=1234&name=john&age=30 HTTP/1.1
Host: example.com
@RequestMapping("/users")
public String getUser(@RequestParam("id") int id,
@RequestParam("name") String name,
@RequestParam("age") int age) {
// 메서드 로직 수행
return "user";
}
@ResponseBody
Spring MVC에서 HTTP 응답 본문을 직접 작성하는데 사용됩니다.
Spring의 컨트롤러 메서드는 View를 반환하는데, @ResponseBody 어노테이션을 사용하면 View 대신 컨트롤러 메서드의 반환 값 자체를 HTTP 응답 본문으로 반환합니다.
@GetMapping("/hello")
@ResponseBody
public String hello() {
return "Hello World!";
}
- @GetMapping은 GET 요청에 대한 매핑을 처리하며,
- @ResponseBody는 컨트롤러 메서드에서 반환하는 문자열을 HTTP 응답의 본문으로 반환합니다.
- "/hello" 요청에 대한 응답으로 "Hello World!" 문자열이 출력
@Configuration
스프링에서 빈(bean)을 정의하고 구성 클래스(configuration class)로 설정
@Configuration 어노테이션을 사용하여 구성 클래스를 정의하면 스프링 컨테이너가 해당 클래스를 자동으로 스캔하여 빈으로 등록합니다. 이후에는 해당 빈을 @Autowired 어노테이션을 사용하여 다른 빈에서 의존성 주입(Dependency Injection)할 수 있습니다.
*다른 클래스에서 myService()와 myRepository() 메서드를 @Autowired 어노테이션을 사용하여 해당 Bean을 주입받아 사용할 수 있다.
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
@Bean
public MyRepository myRepository() {
return new MyRepositoryImpl();
}
}
'Spring' 카테고리의 다른 글
[Spring] 게시판 Repository 을 만들면서 QnA(JpaRepository,Builder,@Modifying,@Transactional) (0) | 2023.03.18 |
---|---|
[Spring] 게시판 Controller을 만들면서 QnA(RequestBody,REST API,Annotation) (0) | 2023.03.12 |
[Spring] Controller VS Service VS Repository (0) | 2023.03.07 |
[Spring] Entity VS DTO VS VO (0) | 2023.03.07 |
[Spring] DDD 설계 와 SQL 설계 (0) | 2023.03.07 |