- ๋ง๊ทธ๋๋ก ๋น์ด ์ฌ์ฉ๋์ด์ง๋ ๋ฒ์์ด๋ค.
- ์คํ๋ง์ด ๊ด๋ฆฌํ๋ ๋น์ด ์์ฑ๋๊ณ , ์กด์ฌํ๊ณ , ์ ์ฉ๋๋ ๋ฒ์๋ฅผ ๋งํ๋ค.
- ๊ธฐ๋ณธ์ ์ฑ๊ธํค์ด๋ค.
- ์์ฒญ๋ง๋ค ๋น์ด ํ๋์ฉ ์์ฑ๋๋ฉด, ์๋ฒ๋ ๋ถํ์ ๊ฑธ๋ฆฌ๊ธฐ ์ฝ๊ธฐ ๋๋ฌธ์ ์คํ๋ง์์๋ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฑ๊ธํค์ ์ฑํํ์๋ค.
- singleton : ๊ธฐ๋ณธ๊ฐ, ์คํ๋ง IoC ์ปจํ ์ด๋๋น ํ๋์ ์ธ์คํด์ค๋ง ์ฌ์ฉํ๋ค. ์ฑ์ด ๊ตฌ๋๋๋ ๋์ ํ๋๋ง ์ฌ์ฉ๋๋ค๋ ๋ป์ด๋ค. ์คํ๋ง์ ๋น์ ๊ธฐ๋ณธ์ผ๋ก ์ฑํดํค ์ค์ฝํ๋ก ์์ฑ๋๋ค.
- prototype : ๋งค๋ฒ ์๋ก์ด ๋น์ ์ ์ํด์ ์ฌ์ฉํ๋ค.
- request : HTTP ์์ฒญ ํ๋๊ฐ ๋ค์ด์ค๊ณ ๋๊ฐ ๋ ๊น์ง ์ ์ง๋๋ ์ค์ฝํ, ๊ฐ๊ฐ์ HTTP ์์ฒญ๋ง๋ค ๋ณ๋์ ๋น ์ธ์คํด์ค๊ฐ ์์ฑ๋๊ณ , ๊ด๋ฆฌ๋๋ค.
- session : HTTP Session๊ณผ ๋์ผํ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ฐ์ง๋ ์ค์ฝํ
- application : ServletContext ์ ๋์ผํ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ฐ์ง๋ ์ค์ฝํ
- websocket : ์น ์์ผ๊ณผ ๋์ผํ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๊ฐ์ง๋ ์ค์ฝํ
@Component
@Scope(value = "prototype") // ์ด๋ถ๋ถ ์ฒ๋ผ, ์ปดํฌ๋ํธ๋ก ๋ฑ๋ก ํ๋ฉด์ ์ด๋
ธํ
์ด์
๋ถ์ฌ์ฃผ๋ฉด ๋จ.
public class ProtoType {
}
- @Scope(value = "prototype")
- @Scope(value = "singleton")
- @Scope(value = "request")
- @Scope(value = "session")
- @Scope(value = "application")
- @Scope(value = "websocket")
- ์ฑ๊ธํค ์ค์ฝํ์ ๋น์ด prototype ์ ๋น์ ์ฃผ์ ๋ฐ๋ ๊ฒฝ์ฐ, prototype ์ ๊ฒฝ์ฐ์๋ ํญ์ ์๋ก์ด ๋น์ด ์์ฑ๋์ด์ผ ํ๋๋ฐ, ๋งค๋ฒ ๊ฐ์ ๋น์ ์ฌ์ฉํ๊ฒ ๋๋ค
@Component
public class Single {
@Autowired
ProtoType protoType; // ์ด ํ๋กํ ํ์
๊ฐ์ฒด์ ๊ฒฝ์ฐ, ํญ์ ๊ฐ์ ๋น์ด ์ฃผ์
๋๋ค.
public ProtoType getProtoType() {
}
}
@Component
@Scope(value = "prototype")
public class ProtoType {
}
- ํ๋กํ ํ์
์ด์ง๋ง, ๋งค๋ฒ ๊ฐ์ ๋น์ ์ฌ์ฉํ๋ ์ด์
- singleton๋น์ย ApplicationContext๊ฐ ์ฒ์ ์ฑ์ ๊ตฌ๋ํ ๋ ๋น์ ๋ง๋ค๊ณ ๋น์ ์ฃผ์ ํด์ ์ฑ์ด ์ข ๋ฃ๋ ๋ ๊น์ง ๊ณ์ ์ฌ์ฉ ๋๊ธฐ ๋๋ฌธ์ย singleton ๋น์์ ์๋ย prototype๋น๋ ์ฒ์ ์ฃผ์ ๋ ์ฑ๋ก ๊ทธ๋๋ก ์ฌ์ฉ๋๋ค.
- ํ๋กํ ํ์ ์ผ๋ก ์ธ ๋น์ด ๊ณ์ ์๋ก์ด ๋น์ผ๋ก ์์ฑ๋๊ฒ ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น?
- proxy mode ๋ฅผ ์ด์ฉํ์.
- ํด๋์ค๋ผ๋ฉด,
@Component
@Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ProtoType {
}
- ๋ง์ฝ ์ธํฐํ์ด์ค๋ผ๋ฉด,
@Component
@Scope(value = "prototype", proxyMode = ScopedProxyMode.INTERFACES)
public interface ProtoType {
}
- scopedProxyMode.DEFAULT : Proxy๋ฅผ ์ฌ์ฉํ์ง ์์
- ํ๋กํ ํ์
๋ชจ๋์์์ ํ๋ก์์ ์๋ฆฌ
- ApplicationContext ๊ฐ ๋น์ ์ฒ์์ ์์ฑํ ๋, ํ๋กํ ํ์ ์ ๋น์ ๊ทธ๋๋ก ๋ฑ๋กํ๋ ๊ฒ์ด ์๋๋ค.
- proxyํด๋์ค๋ฅผ ๋ง๋๋๋ฐ, ์ด ๋ proxy ํด๋์ค๋ ํ๋กํ ํ์ ์ ํด๋์ค(๋๋ ์ธํฐํ์ด์ค)๋ฅผ ์์๋ฐ์์ ๋ง๋ ๋ค. ์ฆ, proxy ํด๋์ค์ ํ๋กํ ํ์ ์ ํด๋์ค๋ ํ์ ์ด ๊ฐ๋ค.
- ์ด proxy ํด๋์ค๋ฅผ ๋น์ผ๋ก ๋ฑ๋กํ๊ณ , proxy ํด๋์ค์์ ๋ด๋ถ์ ์ผ๋ก ๋งค๋ฒ ์๋ก์ด ํ๋กํ ํ์ ์ ๋น์ ์์ฑํด์ ์ฌ์ฉํ๋๋ก ๋์ด์๋ค.
- ์ฌ๋ฌ ๊ณ ๊ฐ๋ค์ ์์ฒญ์ด ๋ค์์ด๋ฉด์ ๋ก๊ทธ๊ฐ ๋ค์ฃฝ๋ฐ์ฃฝ์ผ๋ก ๋จ๋ ๊ฒฝ์ฐ๋ฅผ ๋ฐฉ์งํด์ค ์ ์๋ค.
- ๋ก๊ทธ๋ฅผ ๊ฐ ํด๋ผ์ด์ธํธ ๋ณ๋ก ๊ตฌ๋ถ๋ ์ ์๋๋ก ํ๋ ๊ฒ์ด๋ค.
- ์์
[clientA...][http://localhost:8080/login] controller test
[clientB...][http://localhost:8080/login] controller test
[clientA...][http://localhost:8080/login] service id = testId
[clientB...][http://localhost:8080/login] service id = testId
-
๊ฐ HTTP ์์ฒญ๋ง๋ค ์ค์ฝํ๋ค์ด ๊ด๋ฆฌ๋๋ค.
-
Request ์ค์ฝํ๋ฅผ ๋ง๋ค์ด๋ณด๋ ์ค์ต์ ์๋ ๋งํฌ๋ฅผ ํตํด ์ฐธ๊ณ ํ์ฌ ์งํํ ์ ์๋ค.
- ๋งํฌ : https://chung-develop.tistory.com/64
- Session : ๋ธ๋ผ์ฐ์ ๊ฐ ์ต์ด๋ก ์๋ฒ์ ์์ฒญ์ ํ๊ฒ ๋๋ฉด ๋ธ๋ผ์ฐ์ ๋น ํ๋์ฉ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ ์๋ฒ์ ํ ๋นํ๊ฒ ๋๋ค.
- ์ด ์์ญ์ ๋ธ๋ผ์ฐ์ ๋น ํ๋์ฉ ์ง์ ๋๋ฉฐ, ์๋ก์ด ์์ฒญ์ด ๋ฐ์ํด๋ ๊ฐ์ ๊ณต๊ฐ์ ์ฌ์ฉํ๊ฒ ๋๋ค. ์ด๋ฐ ๋ฉ๋ชจ๋ฆฌ ๊ณต๊ฐ์ session์ด๋ผ๊ณ ํ๋ค.
- ๋ธ๋ผ์ฐ์ ๋ฅผ ์ข ๋ฃํ ๋๊น์ง ์๋ฒ์์ ์ฌ์ฉํ ์ ์๋ค.
- Session ์ค์ฝํ : ๋ธ๋ผ์ฐ์ ๊ฐ ์ต์ด์ ์์ฒญ์ ๋ฐ์์ํค๊ณ , ๋ธ๋ผ์ฐ์ ๋ฅผ ๋ซ์ ๋๊น์ง๋ฅผ session ์ค์ฝํ๋ผ๊ณ ๋ถ๋ฅธ๋ค.
- build.gradle ์ ์ถ๊ฐ
dependencies {
implementation 'org.springframework.session:spring-session-core'
}
@Getter
@Setter
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
@ToString
public class UserInfo implements Serializable {
private static final long serialVersionUID = 1L;
private Long userId;
private String userNm;
}
- proxyMode=TARGET_CLASSย : Bean Scope๋ฅผ session์ผ๋ก ์ค์ ํ ๊ฒฝ์ฐ์๋ proxyMode๋ฅผ TARGE_CLASS๋ก ์ค์ ํด์ฃผ์ด์ผ ํ๋ค.
- Serializableย : ๊ฐ์ฒด๋ฅผ ์ง๋ ฌํ(Serializable)๋ฅผ ํ์ฌ ์ธ๋ถ Redis์ ๊ฐ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ธ์ ์ ์ ์ฅํ ์ ์๋๋ก ํ๋ค. ์ธ๋ถ์ ์ ์ฅํ์ง ์๊ณ ์ ํ๋ฆฌ์ผ์ด์ ์๋ฒ ๋ด์ ๋ฉ๋ชจ๋ฆฌ์์ ํด๊ฒฐํ ๊ณํ์ด๋ผ๋ฉด ๊ตณ์ด ์ง๋ ฌํํ์ง ์์๋ ๋๋ค.
@RestController
@RequestMapping("user")
public class UserController {
@Resource
private UserInfo userInfo;
@Autowired
private UsersRepo usersRepo;
@PostMapping("signin")
public UsersDoc signin(@RequestBody UsersDoc reqBody) {
String userId = reqBody.getUserId();
String passwd = reqBody.getPasswd();
UsersDoc doc = usersRepo.findByUserId(userId)
.filter((data) -> data.getPasswd().equals(passwd))
.orElseThrow(() -> new RestException(HttpStatus.NOT_FOUND, "Check your infomation."));
userInfo.setUserId(doc.getUserId());
userInfo.setUserNm(doc.getUserNm());
return doc;
}
@GetMapping("session")
public String get() {
return userInfo.toString();
}
}
- ์ค๋ช
- ์๋ฒ๋ฅผ ์คํํ๊ณ ย
/user/signin
์ ํธ์ถํด๋ณด๋ฉด, - ๊ทธ๋ผ ์๋ฒ์์ JSESSIONID๋ฅผ ๋ฐ๊ธํด์ฃผ์ด ์ฟ ํค์ ๋ค์ด๊ฐ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค. ํด๋ผ์ด์ธํธ์์ ์๋ฒ๋ก ์์ฒญํ ๋, ์ด ๋ฐ๊ธ๋ฐ์ JSESSIONID๋ฅผ ๋ณด๋ผ๊ฒ์ด๋ค.
/user/session
์ ํธ์ถํด๋ณด๋ฉด userInfo ๊ฐ์ฒด์ ์ ์ฅํ ๋ฐ์ดํฐ๋ฅผ ํ์ธํ ์ ์๋ค.- ๋ค๋ฅธ ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด์,
/user/signin
ํธ์ถํ์ง ์๊ณ ,/user/session
์ ํธ์ถํ๊ฒ ๋๋ฉด ๊ฐ์ด null ์ผ ๊ฒ์ด๋ค.
- ์๋ฒ๋ฅผ ์คํํ๊ณ ย
- ์๋ฒ์์ ๋ฐ๊ธํด์ค JSESSIONID๊ฐ ๋ช ์ด ๋์ ์ ํจํ์ง ์ค์ ํ ์๋ ์๋ค.
- ์๋์ฒ๋ผ 30์ด๋ก ์ง์ ํ๋ฉด 30์ด ๋ค์ JSESSIONID๊ฐ ๋ง๋ฃ๋์ด ์ญ์ ๋๊ณ ๋ค์ Session์ ๋ฐ์ดํฐ๋ฅผ ์ฌ์
๋ ฅ(์ฌ๋ก๊ทธ์ธ , ์ฆ,
/user/signin ์์ฒญ
) ํด์ฃผ์ด์ผ ํ๋ค.
server:
servlet:
session:
timeout: 30s
- ๋๋ถ๋ถ์ ๊ฒฝ์ฐ์๋ ์ธ์ ์ Redis, MongoDB, MySQL ๋ฑ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ์ด ๋๋ค. ์ธ๋ถ์ ์ฐ๋ํ๋ ๋ฐฉ๋ฒ์ ํ์ํ ๋ ์์๋ณด๋ฉด์ ์ ์ฉํด๋ณด๋ฉด ๋ ๋ฏ ํ๋ค.
- https://velog.io/@probsno/Bean-์ค์ฝํ๋
- https://gofnrk.tistory.com/42
- [๋์] ํ ๋น์ ์คํ๋ง 3.1 ์คํ๋ง์ ์ดํด์ ์๋ฆฌ