new ํค์๋ ์์ด ๊ฐ์ฒด๋ฅผ ์์ฑ / ์์กด์ฑ ์ฃผ์
๊ฐ์ฒด ์์ฑ ์๋ฆฌ
์คํ๋ง์์ ์ฒ์ ๊ฐ๋ฐ์ ์์ํ๋ฉด `new` ํค์๋๋ฅผ ์ฌ์ฉํด์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ง ์์๋๋ฐ @Contoller ๋ฑ ๊ฐ์ฒด๋ค์ด ๋ง๋ค์ด์ง๊น?
์ด ์ง๋ฌธ์ ๋ํ ํด๋ต์ Spring์ IoC(์ ์ด๊ถ ์ญ์ , Inversion of Control)์ Spring Container(Applilcation Context)์ ์๋ค.
Spring์์ new ํค์๋๊ฐ ๋ณด์ด์ง ์๋ ์ด์ ๋ Spring์ด ๊ฐ๋ฐ์ ๋์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ด๋ฅผ Bean์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ ๊ณผ์ ์์ Spring์ ์ฑ๊ธํค(Singleton) ํจํด์ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ์ฌ, ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ํจ์จ์ ใ ๋ก ๊ด๋ฆฌํ๊ณ ์๋ฒ์ ์ฑ๋ฅ์ ์ต์ ํํ๋ค.
Spring Bean ์ด๋?
Spring Bean์ด๋ Spring IoC(์ ์ด๊ถ ์ญ์ , Inversion of Control) ์ปจํ ์ด๋์ ์ํด ์์ฑ๋๊ณ ๊ด๋ฆฌ๋๋ ๊ฐ์ฒด๋ฅผ ๋งํ๋ค. ์ฝ๊ฒ ๋งํด, ์ฐ๋ฆฌ๊ฐ ์ง์ new๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ ๋์ , Spring์ด ๋์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ฃผ์ ํด์ฃผ๋ ๋จ์์ด๋ค.
1. Bean ๋ฑ๋ก: Spring Container ๋ด ์ฑ๊ธํค ๊ฐ์ฒด๋ก ๋ฑ๋ก(์ด๋ฏธ `new`๋ก ์ธ์คํด์คํ ๋์ด์๋ค)
2. Bean ์ฌ์ฉ: Spring Container์ ๋ฑ๋ก๋์ด์๋ ์ฑ๊ธํค ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ ์ฃผ์ ํ์ฌ ์ฌ์ฉํ๋ค.
Java Beans์ Spring Beans๋ ๋ค๋ฅด๋ค. Java Beans๋ POJO(Plain Old Java Object)๋ก์ ๋จ์ํ ๋ฐ์ดํฐ๋ง๋ค ๋ด๋ ๊ฐ์ฒด์ง๋ง, Spring Beans๋ Spring ์ปจํ ์ด๋์ ์ํด ์๋ช ์ฃผ๊ธฐ์ ์์กด์ฑ์ด ๊ด๋ฆฌ๋๋ ๊ฐ์ฒด์ด๋ค.
ApplicationContext: ์คํ๋ง ์ปจํ ์ด๋ - ๊ฐ๋ฐ์๊ฐ ์ง์ ๊ฐ์ฑ ์์ฑ X, Spring์ด ๋์ ๊ฐ์ฒด ์์ฑ
- Spring Bean: ๊ฐ๋ฐ์๊ฐ ์ง์ ๊ฐ์ฒด๋ฅผ ์์ฑํ๋๊ฒ ์๋๋ผ Spring์ด ๋์ ๊ฐ์ฒด ์์ฑ ๋ฐ ์ฃผ์
ํด์ฃผ๋ ๋จ์
- Singleton ์ฑ๊ธํด: ์ฑ๊ธํด ๊ฐ์ฒด๋ฅผ Spring์ ApplicationContext๊ฐ ๋์ ๋ง๋ค์ด์ ์ฃผ์
Spring ์ ํ๋ฆฌ์ผ์ด์ ์์๋ ๊ฐ์ฒด๋ฅผ ์ง์ ์์ฑํ ํ์๊ฐ ์๋ค. ์๋ํ๋ฉด ApplicationContexr๋ผ๋ ์คํ๋ง ์ปจํ ์ด๋๊ฐ ์ด๋ฅผ ๋์ ํ๊ธฐ ๋๋ฌธ์ด๋ค. ApplicationContext๋ ์คํ๋ง์ ํต์ฌ์ผ๋ก, IoC ์ปจํ ์ด๋๋ฅผ ํตํด ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ฉฐ, ํ์ํ ๊ฒฝ์ฐ ์์กด์ฑ์ ์ฃผ์ ํ๋ค.
ApplicationContext๋ ๋ ๊ฐ์ง์ ํ์ ์ผ๋ก ๋ถ๋ฅ๋๋ค.
- Servlet WebApplicationContext: @Controller, @RestController ๋ฑ์ MVC ๊ด๋ จ ๋น์ ๊ด๋ฆฌ.
- Root WebApplicationContext: @Service, @Repository ๊ฐ์ ์ ํ๋ฆฌ์ผ์ด์ ๋ก์ง ๊ด๋ จ ๋น์ ๊ด๋ฆฌ
Spring์ ApplicationContext์ Bean ์ฃผ์ ์์
package com.example.demo.controller;
import com.example.demo.service.User;
import com.example.demo.service.UserServiceInterface;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.List;
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserServiceInterface userService;
@Autowired
private ApplicationContext applicationContext;
@GetMapping("/bean")
@ResponseBody
public String bean() {
return applicationContext.getBean(UserServiceInterface.class).toString();
}
@GetMapping("")
public String userPage(Model model) {
List<User> users = userService.findAll();
model.addAttribute("users", users);
return "/users/list";
}
@GetMapping("/1/detail")
public String detailPage(Model model) {
User user = userService.findById(1);
model.addAttribute("id", user.getId());
model.addAttribute("name", user.getName());
model.addAttribute("age", user.getAge());
model.addAttribute("job", user.getJob());
model.addAttribute("specialty", user.getSpecialty());
return "/users/detail";
}
@GetMapping("/1/data")
@ResponseBody
public User detailData() {
User user = userService.findById(1);
return user;
}
}
์ฝ๋ ์ค๋ช
1. ์์กด์ฑ ์ฃผ์ (@Autowired)
- @Autowired ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ฌ, UserServiceInterface์ ApplicationContext๊ฐ ์๋์ผ๋ก ์ฃผ์ ๋๋ค.
- Spring IoC ์ปจํ ์ด๋(ApplicationContext)๊ฐ ์ด ๊ฐ์ฒด๋ค์ ๊ด๋ฆฌํ๊ณ , ์๋์ผ๋ก ์์กด์ฑ์ ์ฃผ์ ํด์ค๋ค.
@Autowired
private UserServiceInterface userService;
@Autowired
private ApplicationContext applicationContext;
2. Bean ํ์ธ
- /users/bean ๊ฒฝ๋ก๋ก ์ ๊ทผํ๋ฉด ApplicationContext์์ UserServiceInterface์ Bean์ ๊ฐ์ ธ์ ๋ฌธ์์ด๋ก ๋ฐํํ๋ค.
- ์ด๋ฅผ ํตํด Spring์ด ์ค์ ๋ก Bean์ ์ด๋ป๊ฒ ๊ด๋ฆฌํ๋์ง ํ์ธํ ์ ์๋ค.
@GetMapping("/bean")
@ResponseBody
public String bean() {
return applicationContext.getBean(UserServiceInterface.class).toString();
}
3. ์ฌ์ฉ์ ๋ชฉ๋ก์ ๋ชจ๋ธ์ ๋ด๊ธฐ
- /users ๊ฒฝ๋ก๋ก ์ ๊ทผํ๋ฉด, UserServiceInterface๋ฅผ ํตํด ๋ชจ๋ ์ฌ์ฉ์ ๋ชฉ๋ก์ ๊ฐ์ ธ์ Model ๊ฐ์ฒด์ ๋ด๋๋ค.
- ์ด ๋ชจ๋ธ ๋ฐ์ดํฐ๋ /users/list ๋ทฐ๋ก ์ ๋ฌ๋์ด ์ฌ์ฉ์ ๋ชฉ๋ก์ ๋ ๋๋งํ๋๋ฐ ์ฌ์ฉ๋๋ค.
@GetMapping("")
public String userPage(Model model) {
List<User> users = userService.findAll();
model.addAttribute("users", users);
return "/users/list";
}
4. ํน์ ์ฌ์ฉ์ ์์ธ ์ ๋ณด ํ์ด์ง
- /users/1/detail ๊ฒฝ๋ก๋ก ์ ๊ทผํ๋ฉด, id๊ฐ 1์ธ ์ฌ์ฉ์์ ์์ธ ์ ๋ณด๋ฅผ ์กฐํํ์ฌ ๋ชจ๋ธ์ ๋ด๋๋ค.
- ์ด ์ ๋ณด๋ /users/detail ํ์ด์ง์์ ์ฌ์ฉ๋๋ค.
@GetMapping("/1/detail")
public String detailPage(Model model) {
User user = userService.findById(1);
model.addAttribute("id", user.getId());
model.addAttribute("name", user.getName());
model.addAttribute("age", user.getAge());
model.addAttribute("job", user.getJob());
model.addAttribute("specialty", user.getSpecialty());
return "/users/detail";
}
5. ํน์ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ JSON์ผ๋ก ๋ฐํ
- /users/1/data ๊ฒฝ๋ก๋ก ์ ๊ทผํ๋ฉด, id๊ฐ 1์ธ ์ฌ์ฉ์์ ๋ฐ์ดํฐ๋ฅผ JSON ํ์์ผ๋ก ๋ฐํํ๋ค.
- @ResponseBody ์ด๋ ธํ ์ด์ ์ ํตํด ๋ฐํ๋๋ ๊ฐ์ฒด๊ฐ JSOn์ผ๋ก ์ง๋ ฌํ๋๋ค.
@GetMapping("/1/data")
@ResponseBody
public User detailData() {
User user = userService.findById(1);
return user;
}
Spring Bean์ Scope์ ๋ฐ๋ฅธ Bean์ ๋ผ์ดํ ์ฌ์ดํด
Spring์์ ๊ด๋ฆฌํ๋ Bean์ ๊ธฐ๋ณธ ๋ฒ์๋ ์ฑ๊ธํค(Singleton)์ด๋ค. ํ์ง๋ง ์ํฉ์ ๋ฐ๋ผ ๋ค๋ฅธ ์ค์ฝํ๋ฅผ ์ฌ์ฉํด์ผํ ๋๋ ์๋ค.
- Singleton Scope (๊ธฐ๋ณธ ์ค์ฝํ): Spring IoC ์ปจํ ์ด๋์ ์ํด ํ ๊ฐ์ ๊ฐ์ฒด๋ก ๊ด๋ฆฌ๋๋ค.
@Component
public class SingletonBean {
}
- Prototype Scope: ๋งค๋ฒ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค.(๊ฐ์ฒด ์๋ฉธ์ Garbage Collection์๊ฒ ์์)
@Component
@Scope("prototype")
public class PrototypeBean {
}
- Request Scope: HTTP ์์ฒญ๋ง๋ค ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค. ์๋ต๋๊ธฐ๊น์ง ์๋ธ๋ฆฟ ๊ธฐ๋ฐ WebAppllicationContext๊ฐ ๊ด๋ฆฌํ๋ค.
@Component
@RequestScope
public class RequestBean {
}
- Session Scope: HTTP ์ธ์ ๋ง๋ค ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค. ์ด ๋ํ ์๋ธ๋ฆฟ ๊ธฐ๋ฐ WebApplicationContext๊ฐ ๊ด๋ฆฌํ๋ค.
@Component
@SessionScope
public class SessionBean {
}
Spring ์ ์ด ์ญ์ (IoC, Inversion of Control)
์ ์ด์ ์ญ์ (IoC, Inversion of Control)์ ๊ฐ์ฒด์ ์์ฑ์ ๊ฐ๋ฐ์๊ฐ ์ง์ ํ๋ ๊ฒ์ด ์๋๋ผ, Spring์ด ๋์ ๊ด๋ฆฌํ๊ณ ํ์ํ ๊ณณ์ ์ฃผ์ ํด์ฃผ๋ ์๋ฆฌ๋ฅผ ์๋ฏธํ๋ค. IoC๋ ์์กด์ฑ ์ฃผ์ (DI: Dependency Injection)์ ํตํด ๊ตฌํ๋๋ฉฐ, ์ด๋ Spring์ Bean ๊ด๋ฆฌ์ ์์ด์ ๋งค์ฐ ์ค์ํ ๊ฐ๋ ์ด๋ค.
Service Locator: ๊ฐ๋ฐ์๊ฐ ์ง์ ์ฃผ์ ํ๋ค.
- Locator๊ฐ ์ง์ ์ฃผ์ + ์์กด์ฑ ํ์ ๋ถ๊ฐ
- ํ ์คํธ ์ ์ธ๋ถ์์ Mock, Stub ์ฃผ์ ๋ถ๊ฐ
DI: ์ปจํ ์ด๋๊ฐ ๋์ Bean ์ฃผ์
- ์์ฑ์๋ง์ผ๋ก ์ฃผ์ + ์์กด์ ํ์ ๊ฐ๋ฅ
- ํ ์คํธ ์ ์ธ๋ถ์์ Mock, Stub ์ฃผ์ ๊ฐ๋ฅ
Bean ์ฃผ์ ๋ฐฉ๋ฒ
Spring์์๋ ๋ค์ํ ๋ฐฉ์์ผ๋ก ์์กด์ฑ์ ์ฃผ์ ํ ์ ์๋ค.
- ์์ฑ์ ์ฃผ์
(Constructor Injection, Spring ๊ณต์ ์ถ์ฒ): ์ค์ ํ์
์์ ๊ฐ์ฅ ๋ง์ด ์ฌ์ฉํ๋ ์ฝ๋
- ์ฅ์ (1): ์ํ์ฐธ์กฐ๋ฅผ ์ปดํ์ผ ์ ๋ฐฉ์ง → ์ํ์ฐธ์กฐ ์ฌ๋ถ๋ฅผ ๊ฐ์ฒด ์์ฑ ํ๊ฐ ์๋ ์์ฑ ์ ์ ์ธ์งํด ์ค์๋ฅผ ๋ฐฉ์ง
- ์ฅ์ (2): Final ์ ์ฉ ๊ฐ๋ฅ → Bean ๊ฐ์ฒด์ ๋ถ๋ณ์ฑ ๋ณด์ฅ(ํ๋ฒ ์ฃผ์ ๋๋ฉด ์ดํ์ ๋ฐ๋์ง ์๋๋ค๋ ๊ฒ์ ๋ณด์ฅํ๋ค.
@Controller
@RequestMapping("/users")
@RequiredArgsConstructor // ์์ฑ์ ์ฃผ์
public class UserController {
private final UserServiceInterface userService;
์ ์ฝ๋์ฒ๋ผ `private final`์ ๋ถํ์ฃผ๋ ๋ฐฉ๋ฒ๋ ์๊ณ ,
@Controller
@RequestMapping("/users")
@RequiredArgsConstructor
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class UserController {
UserServiceInterface userService;
์ ์ฝ๋์ฒ๋ผ `FieldDefaults`๋ก ๋ช ์ํ๋ ๋ฐฉ๋ฒ์ด ์๋ค.
- ํ๋ ์ฃผ์ (Property Injection): ์ฃผ๋์ด ๊ฐ๋ฐ์๋ค์ด ๊ฐ์ฅ ๋ง์ด ์ ํธํ๋ ์ง๊ด์ ์ธ ๋ฐฉ์์ด๋ค. ํ๋์ ์ง์ @Autowired๋ฅผ ์ฌ์ฉํ์ฌ ์ฃผ์ ํ๋ ๋ฐฉ์์ด๋ค.
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired // ํ๋ ์ฃผ์
private UserServiceInterface userService;
- ์์ ์ ์ฃผ์ ((Setter) Method Injection): ์์ ์ ๋ฉ์๋๋ฅผ ํตํด ์ฃผ์ ํ๋ ๋ฐฉ์์ผ๋ก, ํน์ ์ํฉ์์ ์ ํ์ ์ผ๋ก ์์กด์ฑ์ ์ฃผ์ ํ ๋ ์ ์ฉ.
@Controller
@RequestMapping("/users")
public class UserController {
private UserServiceInterface userService;
@Autowired // ์์ ์ ์ฃผ์
public void setUserService(UserServiceInterface userService) {
this.userService = userService;
}
โน๏ธ ์ฐธ๊ณ
[ASAC 6๊ธฐ ๊ฐ์์๋ฃ]
'๐ปDEV-STUDY > Spring' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] Spring Boot ์ฅ์ ๋ฐ ๋์ (0) | 2024.10.06 |
---|---|
[Spring] Spring ์์ฒญ๊ฐ ์ฒ๋ฆฌ ๋ฐฉ์ (0) | 2024.10.06 |
[Spring]HttpMessageConverter (0) | 2024.10.06 |
[Spring] Controller ์ฒ๋ฆฌ ๋ฐํ (1) | 2024.10.05 |
[Spring] Spring Controller์ ๊ธฐ๋ณธ ๋์ (0) | 2024.10.04 |