ํญํด99๋ฅผ ์์ํ์ง ์ด์ 4์ฃผ์ฐจ๊ฐ ๋๋ค. 3์ฃผ์ฐจ ์ฃผํน๊ธฐ ์ ๋ฌธ์์ ์ฒ์์ผ๋ก Spring์ ์ฌ์ฉํด๋ดค๋ค. Spring์ด ์ด๋ ต๋ค๊ณ ์ด์ผ๊ธฐ๋ง ๋ค์๋๋ฐ ์๊ฐ๋ณด๋ค ๋๋ฌด ํธํ๋ค. ํ์ง๋ง ํธํ๋งํผ ๋ด๋ถ์ ์ผ๋ก ์ด๋ป๊ฒ ๋์ํ๋์ง ์ ์ดํด๊ฐ๊ฐ์ง ์๋ ๋จ์ ์ด ์๋ค. ์ด์ Spring์ ์ ๋๋ก ๊ณต๋ถํ ์๊ฐ์ด 4์ฃผ์ฐจ 5์ฃผ์ฐจ 2์ฃผ๊ฐ์ ์๊ฐ์ด ๋จ์๋๋ฐ ์ธํ๋ฐ์ Spring๊ฐ์๋ฅผ ๊ตฌ๋งคํด์ ๋ค์ด๋ณผ๊น ๊ณ ๋ฏผ์ค์ด๋ค.
Spring์์ ์ค์ํ ๊ฐ๋ 3๊ฐ์ง๋ฅผ ํ ๋ฒ ์ ๋ฆฌํด๋ณผ๊นํ๋ค.
์์กด์ฑ ์ฃผ์ ( Dependency Injection ) : ํ๋์ ๊ฐ์ฒด๊ฐ ๋ค๋ฅธ ๊ฐ์ฒด์ ์์กด์ฑ์ ์ ๊ณตํ๋ ํ ํฌ๋์ด๋ค.
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
@PostMapping("members/new")
public String create(MemberForm form){
Member member = new Member();
member.setName(form.getName());
memberService.join(member);
return "redirect:/";
}
}
@Autowired
์ด๋
ธํ
์ด์
์ถ๊ฐ public MemberController(MemberService memberService) {
this.memberService = memberService;
}
@RestController
@RequiredArgsConstructor
public class PostController {
private final PostRepository postRepository;
private final PostService postService;
@PostMapping("/posts")
public Post createPost(@RequestBody PostRequestDto requestDto){
Post post = new Post(requestDto);
return postRepository.save(post);
}
}
@RequiedArgsConstructor
์ด๋
ธํ
์ด์
์ถ๊ฐ๋ง ํด์ฃผ๋ฉด ๋จ.์ ์ด์ ์ญ์ ( Inversion of Control ) : ํ๋ก๊ทธ๋๋จธ๊ฐ ์์ฑํ ํ๋ก๊ทธ๋จ์ด ์ฌ์ฌ์ฉ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ๋ฆ ์ ์ด๋ฅผ ๋ฐ๊ฒ ๋๋ ์ํํธ์จ์ด ๋์์ธ ํจํด์ ๋งํ๋ค.
- ์ผ๋ฐ์ ์ผ๋ก ์ฒ์์ ๋ฐฐ์ฐ๋ ์๋ฐ ํ๋ก๊ทธ๋จ์์๋ ๊ฐ ๊ฐ์ฒด๋ค์ด ํ๋ก๊ทธ๋จ์ ํ๋ฆ์ ๊ฒฐ์ ํ๊ณ ๊ฐ ๊ฐ์ฒด๋ฅผ ์ง์ ์์ฑํ๊ณ ์กฐ์ํ๋ ์์ (๊ฐ์ฒด๋ฅผ ์ง์ ์์ฑํ์ฌ ๋ฉ์๋ ํธ์ถ)์ ํ๋ค. ์ฆ, ๋ชจ๋ ์์ ์ ์ฌ์ฉ์๊ฐ ์ ์ดํ๋ ๊ตฌ์กฐ์๋ค.
- ์๋ฅผ ๋ค์ด A ๊ฐ์ฒด์์ B ๊ฐ์ฒด์ ์๋ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ผ๋ฉด, B ๊ฐ์ฒด๋ฅผ ์ง์ A ๊ฐ์ฒด ๋ด์์ ์์ฑํ๊ณ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ค.
- ํ์ง๋ง IOC๊ฐ ์ ์ฉ๋ ๊ฒฝ์ฐ, ๊ฐ์ฒด์ ์์ฑ์ ํน๋ณํ ๊ด๋ฆฌ ์์ ์ฃผ์ฒด์๊ฒ ๋งก๊ธด๋ค. ์ด ๊ฒฝ์ฐ ์ฌ์ฉ์๋ ๊ฐ์ฒด๋ฅผ ์ง์ ์์ฑํ์ง ์๊ณ , ๊ฐ์ฒด์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ์ปจํธ๋กคํ๋ ์ฃผ์ฒด๋ ๋ค๋ฅธ ์ฃผ์ฒด๊ฐ ๋๋ค.
- ์ฆ, ์ฌ์ฉ์์ ์ ์ด๊ถ์ ๋ค๋ฅธ ์ฃผ์ฒด์๊ฒ ๋๊ธฐ๋ ๊ฒ์ IOC(์ ์ด์ ์ญ์ ) ๋ผ๊ณ ํฉ๋๋ค.
์คํ๋ง ๋น(Spring Bean) : Spring IoC ์ปจํ ์ด๋๊ฐ ๊ด๋ฆฌํ๋ ์๋ฐ ๊ฐ์ฒด๋ฅผ ๋งํ๋ค.
์๋ฐ ์ด๋ ธํ ์ด์ ์ฐธ๊ณ !
์ด๋ ธํ ์ด์ ์์
public class Parent {
public void doSomething() {
System.out.println("This is Parent");
}
}
public class Son extends Parent{
@Override
public void doSomething() {
System.out.println("This is Son");
}
}
๊ทธ๋ผ ์ค์ Spring์์ ์ด๋ค ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํด Bean ๋ฑ๋กํ ๊น?
Spring @Component ์์
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
@GetMapping("/members/new")
public String createForm(){
return "/members/createMemberForm";
}
}
์ @Component๊ฐ ์์ง? ๋ผ๊ณ ์๊ฐํ ์ ์๋ค. ํด๋น ๋ถ๋ถ์ ํ์ธํ๊ธฐ ์ํด์ ์ธํ ๋ฆฌ์ ์ด๋ฅผ ์ฌ์ฉํ๋ค๋ฉด Ctrl์ ๋๋ฅธ ์ํ๋ก @Controller๋ฅผ ํด๋ฆญํด๋ณธ๋ค. ๊ทธ๋ผ ์๋์ ๊ฐ์ ์ฝ๋๋ฅผ ํ์ธํ ์ ์๋ค.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
/**
* The value may indicate a suggestion for a logical component name,
* to be turned into a Spring bean in case of an autodetected component.
* @return the suggested component name, if any (or empty String otherwise)
*/
@AliasFor(annotation = Component.class)
String value() default "";
}
์ @Controller ์ด๋ ธํ ์ด์ ์ฝ๋์์ @Component๊ฐ ์์์ ํ์ธํ ์ ์๋ค.
@Component ์ด๋ ธํ ์ด์ ์ ํตํด Spring์ ํด๋น Controller๋ฅผ Bean์ผ๋ก ๋ฑ๋กํ๋ค.
@Configuration๊ณผ @Bean ์ด๋ ธํ ์ด์ ์ ์ด์ฉํ์ฌ Bean์ ๋ฑ๋กํ ์ ์๋ค.
์๋์ ์์ ์ ๊ฐ์ด @Configuration์ ์ด์ฉํ๋ฉด Spring ํ๋ก์ ํธ์์์ Configuration ์ญํ ์ ํ๋ Class๋ฅผ ์ง์ ํ ์ ์๋ค.
ํด๋น ํ์ผ ํ์์ Bean์ผ๋ก ๋ฑ๋กํ๊ณ ์ ํ๋ Class์ @Bean ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํด์ฃผ๋ฉด ๊ฐ๋จํ๊ฒ Bean์ ๋ฑ๋กํ ์ ์๋ค.
@Configuration
public class SpringConfig {
private final DataSource dataSource;
private final EntityManager em;
@Autowired
public SpringConfig(DataSource dataSource, EntityManager em) {
this.dataSource = dataSource;
this.em = em;
}
@Bean
public MemberService memberService(){
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository(){
return new JpaMemberRepository(em);
}
}