문제 아래의 코드를 우선 읽어보자.
해결 전 심각한 코드 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @Controller public class NoReadRecipientMailboxController { @Autowired private NoReadRecipientMailboxMapper recipientMailboxMapper; private String user_id_session; private String searchContent; private List<RecipientEmail> recipientEmail; private List<RecipientEmail> recipientStarEmail; private List<RecipientEmail> recipientSearchEmail; @GetMapping("/noreadreceivemailbox") public String mailbox (Model model, HttpServletRequest req) { user_id_session = (String)req.getSession().getAttribute("user_id" ); recipientEmail = recipientMailboxMapper.selectList(user_id_session); model.addAttribute("noreadrecipientEmail" , recipientEmail); recipientStarEmail = recipientMailboxMapper.selectStarList(user_id_session); model.addAttribute("noreadrecipientStarEmail" , recipientStarEmail); recipientSearchEmail = recipientMailboxMapper.searchMailTitle(searchContent, user_id_session); model.addAttribute("noreadrecipientSearchEmail" , recipientSearchEmail); this .searchContent = "" ; return "mailbox/noreadreceivemailbox" ; } @PutMapping("/noreadreceivemailbox/searchMail/title/{searchContent}") public ResponseEntity<?> searchMailTitle (@PathVariable String searchContent) { this .searchContent = "%" + searchContent + "%" ; return new ResponseEntity<>(true , HttpStatus.OK); } }
문제점 발견 코드를 잘 읽어보면 처음에는 어떤 문제가 있는지 잘 모르는 경우가 많다. 하지만 이 코드는 굉장한 문제점을 가지고 있고, 이제부터 이 문제점을 해결해나가고자 한다.
1 private List<RecipientEmail> recipientEmail;
이러한 방식으로 메소드 외부에 인스턴스 변수를 생성했을 때 스프링은 최초 동작 시에만 새롭게 생성하고, 이후에는 해당 변수를 그대로 반환한다. 그리고 싱글톤은 Thread-Safety
하지 않다! 여러 사용자가 동시에 이 서비스를 이용하는 경우에 다른 사용자의 값을 반환받을 경우도 생기는 것이다. 이렇게 되면 다른 사용자의 메일을 볼 수 있을지도 모른다. 아니 실제로 그런 일이 발생한다.
그러므로 아래처럼 메소드 내부에 변수를 선언하는 것이 중요하다.
해결 후 코드 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 @Controller public class NoReadRecipientMailboxController { @Autowired private NoReadRecipientMailboxMapper recipientMailboxMapper; @GetMapping("/noreadreceivemailbox") public String mailbox (Model model, HttpServletRequest req, String searchContent, String view) { String user_id_session = (String)req.getSession().getAttribute("user_id" ); if (searchContent != null ) { String Content = "%" + searchContent + "%" ; List<RecipientEmail> recipientSearchEmail = recipientMailboxMapper.searchMailTitle(Content, user_id_session); model.addAttribute("noreadrecipientSearchEmail" , recipientSearchEmail); } else if (view != null && view.equals("star" )){ List<RecipientEmail> recipientStarEmail = recipientMailboxMapper.selectStarList(user_id_session); model.addAttribute("noreadrecipientStarEmail" , recipientStarEmail); } else { List<RecipientEmail> recipientEmail = recipientMailboxMapper.selectList(user_id_session); model.addAttribute("noreadrecipientEmail" , recipientEmail); } return "mailbox/noreadreceivemailbox" ; } }