Skip to content

Latest commit

ย 

History

History
221 lines (161 loc) ยท 7.72 KB

Bean Scope.md

File metadata and controls

221 lines (161 loc) ยท 7.72 KB

๋นˆ ์Šค์ฝ”ํ”„๋ž€ ?

  • ๋ง๊ทธ๋Œ€๋กœ ๋นˆ์ด ์‚ฌ์šฉ๋˜์–ด์ง€๋Š” ๋ฒ”์œ„์ด๋‹ค.
  • ์Šคํ”„๋ง์ด ๊ด€๋ฆฌํ•˜๋Š” ๋นˆ์ด ์ƒ์„ฑ๋˜๊ณ , ์กด์žฌํ•˜๊ณ , ์ ์šฉ๋˜๋Š” ๋ฒ”์œ„๋ฅผ ๋งํ•œ๋‹ค.
  • ๊ธฐ๋ณธ์€ ์‹ฑ๊ธ€ํ†ค์ด๋‹ค.
  • ์š”์ฒญ๋งˆ๋‹ค ๋นˆ์ด ํ•˜๋‚˜์”ฉ ์ƒ์„ฑ๋˜๋ฉด, ์„œ๋ฒ„๋Š” ๋ถ€ํ•˜์— ๊ฑธ๋ฆฌ๊ธฐ ์‰ฝ๊ธฐ ๋•Œ๋ฌธ์— ์Šคํ”„๋ง์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์‹ฑ๊ธ€ํ†ค์„ ์ฑ„ํƒํ•˜์˜€๋‹ค.

๋นˆ ์Šค์ฝ”ํ”„์˜ ์ข…๋ฅ˜

  • 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 ์˜ ๊ฒฝ์šฐ์—๋Š” ํ•ญ์ƒ ์ƒˆ๋กœ์šด ๋นˆ์ด ์ƒ์„ฑ๋˜์–ด์•ผ ํ•˜๋Š”๋ฐ, ๋งค๋ฒˆ ๊ฐ™์€ ๋นˆ์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค

Single.java

@Component
public class Single {

    @Autowired
    ProtoType protoType; // ์ด ํ”„๋กœํ† ํƒ€์ž… ๊ฐ์ฒด์˜ ๊ฒฝ์šฐ, ํ•ญ์ƒ ๊ฐ™์€ ๋นˆ์ด ์ฃผ์ž…๋œ๋‹ค.

    public ProtoType getProtoType() {
    }
}

Prototype.java

@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 ํด๋ž˜์Šค์—์„œ ๋‚ด๋ถ€์ ์œผ๋กœ ๋งค๋ฒˆ ์ƒˆ๋กœ์šด ํ”„๋กœํ† ํƒ€์ž…์˜ ๋นˆ์„ ์ƒ์„ฑํ•ด์„œ ์‚ฌ์šฉํ•˜๋„๋ก ๋˜์–ด์žˆ๋‹ค.



request ์Šค์ฝ”ํ”„

  • ์—ฌ๋Ÿฌ ๊ณ ๊ฐ๋“ค์˜ ์š”์ฒญ์ด ๋’ค์„ž์ด๋ฉด์„œ ๋กœ๊ทธ๊ฐ€ ๋’ค์ฃฝ๋ฐ•์ฃฝ์œผ๋กœ ๋‚จ๋Š” ๊ฒฝ์šฐ๋ฅผ ๋ฐฉ์ง€ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.
  • ๋กœ๊ทธ๋ฅผ ๊ฐ ํด๋ผ์ด์–ธํŠธ ๋ณ„๋กœ ๊ตฌ๋ถ„๋  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด๋‹ค.
  • ์˜ˆ์‹œ
[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 ์š”์ฒญ๋งˆ๋‹ค ์Šค์ฝ”ํ”„๋“ค์ด ๊ด€๋ฆฌ๋œ๋‹ค.

    IMAGES

  • Request ์Šค์ฝ”ํ”„๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋Š” ์‹ค์Šต์€ ์•„๋ž˜ ๋งํฌ๋ฅผ ํ†ตํ•ด ์ฐธ๊ณ ํ•˜์—ฌ ์ง„ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.




Session ์Šค์ฝ”ํ”„

  • Session : ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ตœ์ดˆ๋กœ ์„œ๋ฒ„์— ์š”์ฒญ์„ ํ•˜๊ฒŒ ๋˜๋ฉด ๋ธŒ๋ผ์šฐ์ €๋‹น ํ•˜๋‚˜์”ฉ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ ์„œ๋ฒ„์— ํ• ๋‹นํ•˜๊ฒŒ ๋œ๋‹ค.
    • ์ด ์˜์—ญ์€ ๋ธŒ๋ผ์šฐ์ € ๋‹น ํ•˜๋‚˜์”ฉ ์ง€์ •๋˜๋ฉฐ, ์ƒˆ๋กœ์šด ์š”์ฒญ์ด ๋ฐœ์ƒํ•ด๋„ ๊ฐ™์€ ๊ณต๊ฐ„์„ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค. ์ด๋Ÿฐ ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„์„ session์ด๋ผ๊ณ  ํ•œ๋‹ค.
    • ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์ข…๋ฃŒํ•  ๋•Œ๊นŒ์ง€ ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Session ์Šค์ฝ”ํ”„ : ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์ตœ์ดˆ์˜ ์š”์ฒญ์„ ๋ฐœ์ƒ์‹œํ‚ค๊ณ , ๋ธŒ๋ผ์šฐ์ €๋ฅผ ๋‹ซ์„ ๋•Œ๊นŒ์ง€๋ฅผ session ์Šค์ฝ”ํ”„๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

์˜ˆ์‹œ

  • build.gradle ์— ์ถ”๊ฐ€
dependencies {
	implementation 'org.springframework.session:spring-session-core'
}

UserInfo.java

@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์™€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์„ธ์…˜์„ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค. ์™ธ๋ถ€์— ์ €์žฅํ•˜์ง€ ์•Š๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์„œ๋ฒ„ ๋‚ด์— ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด๊ฒฐํ•  ๊ณ„ํš์ด๋ผ๋ฉด ๊ตณ์ด ์ง๋ ฌํ™”ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

UserController.java

@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 ์ผ ๊ฒƒ์ด๋‹ค.

application.yml

  • ์„œ๋ฒ„์—์„œ ๋ฐœ๊ธ‰ํ•ด์ค€ JSESSIONID๊ฐ€ ๋ช‡ ์ดˆ ๋™์•ˆ ์œ ํšจํ•œ์ง€ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
  • ์•„๋ž˜์ฒ˜๋Ÿผ 30์ดˆ๋กœ ์ง€์ •ํ•˜๋ฉด 30์ดˆ ๋’ค์— JSESSIONID๊ฐ€ ๋งŒ๋ฃŒ๋˜์–ด ์‚ญ์ œ๋˜๊ณ  ๋‹ค์‹œ Session์— ๋ฐ์ดํ„ฐ๋ฅผ ์žฌ์ž…๋ ฅ(์žฌ๋กœ๊ทธ์ธ , ์ฆ‰, /user/signin ์š”์ฒญ) ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.
server:
  servlet:
    session:
      timeout: 30s
  • ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ์—๋Š” ์„ธ์…˜์€ Redis, MongoDB, MySQL ๋“ฑ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ์ด ๋œ๋‹ค. ์™ธ๋ถ€์™€ ์—ฐ๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ํ•„์š”ํ•  ๋•Œ ์•Œ์•„๋ณด๋ฉด์„œ ์ ์šฉํ•ด๋ณด๋ฉด ๋  ๋“ฏ ํ•˜๋‹ค.

Reference