** ๐ PART 8.1 Memory Safe MVC ๊ตฌ์กฐ๋ก ๊ฐ์ ํ๊ธฐ **
โ๋ฉ๋ชจ๋ฆฌ๋ ์์ ํ๊ณ , ์ ์ง๋ณด์๋ ์ฌ์ด ๊ตฌ์กฐ๋ก ์ฝ๋๋ฅผ ์ ๋ฆฌํด๋ณด์!โ
๐ง ํต์ฌ ๋ชฉํ:
- ๋์ ์ฌ์ฉ์ ์๊ฐ ๋์ด๋๋ ์์ ํ ๊ตฌ์กฐ
- GC๊ฐ ์ ์ ๋ฆฌํ ์ ์๋๋ก ๊ฐ์ฒด ์๋ช ์กฐ์
- ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๊ฐ์ฒด๋ ํจ์จ์ ์ผ๋ก ๊ณต์
๐ข 1๋จ๊ณ. MVC2 ๊ตฌ์กฐ์์ ๋ฉ๋ชจ๋ฆฌ ์ํ ์ง์ ์ ์ด๋?
๐ฆ ๊ธฐ๋ณธ ๊ตฌ์กฐ
[Client] โ Controller โ Service โ DAO โ DB
โ
View(JSP)
โ ๋ฉ๋ชจ๋ฆฌ ์ํ ํฌ์ธํธ
๋ ์ด์ด | ์๋ชป๋ ์ฌ์ฉ | ๋ฌธ์ ์ |
---|---|---|
Controller | ๋งค ์์ฒญ๋ง๋ค ๊ฐ์ฒด ์์ฑ | GC ๋์ ๋ง์์ง |
Service | ์ํ ์๋ ๊ฐ์ฒด ๊ณต์ | Thread-safe ๋ฌธ์ ๋ฐ์ ๊ฐ๋ฅ |
DAO | DB ์ฐ๊ฒฐ์ ์ง์ ๊ด๋ฆฌ | Connection ๋์, ๋ฉ๋ชจ๋ฆฌ ๊ณผ๋ค ์ฌ์ฉ |
โ ๋ฆฌํฉํ ๋ง ์ ๋ต 1: Controller / Service / DAO ๋ฉ๋ชจ๋ฆฌ ์์ ์ค๊ณ
โ [1] Controller: ์ํ ์๋ ์ฑ๊ธํค + ๋ฉ์๋ ๋จ์ ์ฒ๋ฆฌ
@WebServlet("/member/list")
public class MemberController extends HttpServlet {
private MemberService service = new MemberService(); // โ
์ํ ์์!
protected void doGet(HttpServletRequest req, HttpServletResponse res) {
List<Member> list = service.getAll();
req.setAttribute("list", list);
req.getRequestDispatcher("memberList.jsp").forward(req, res);
}
}
๐ก ํต์ฌ
- Controller๋ ์ฑ๊ธ ์ธ์คํด์ค๋ก ์ ์ง๋จ (์๋ฒ ์์ ์ 1ํ ์์ฑ)
- ์ธ์คํด์ค ๋ณ์์ ์ฌ์ฉ์๋ณ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ์ง ์๋๋ค!
โ [2] Service: ์ํ ์๋ ๊ฐ์ฒด, ์์ฒญ๋ง๋ค ๋์๋ง ์ํ
public class MemberService {
private MemberDao dao = MemberDao.getInstance(); // โ
DAO๋ ์ฑ๊ธํค
public List<Member> getAll() {
return dao.selectAll();
}
}
๐ก ํต์ฌ
- Service๋ ์ํ๋ฅผ ์ ์ฅํ์ง ์์
- ๋ฐ์ดํฐ๋ ๋ฉ์๋ ๋งค๊ฐ๋ณ์/๋ฆฌํด๊ฐ์ผ๋ก๋ง ์ ๋ฌ โ GC ์๊ฑฐ ์ฌ์
โ [3] DAO: ์ฑ๊ธํค + ์ปค๋ฅ์ ํ ์ฌ์ฉ + ์ํ ์์
public class MemberDao {
private static final MemberDao instance = new MemberDao();
private MemberDao() {} // ์์ฑ์ private
public static MemberDao getInstance() {
return instance;
}
public List<Member> selectAll() {
try (Connection conn = DBConnection.getConnection();
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM member")) {
...
}
}
}
๐ก ํต์ฌ
- DAO๋ ์ฑ๊ธํค์ผ๋ก ํ ๋ฒ๋ง ์์ฑ๋จ โ ๋ฉ๋ชจ๋ฆฌ ํจ์จ โ
- DB ์ฐ๊ฒฐ์ ํญ์ try-with-resources๋ก ์๋ ์ ๋ฆฌ
โ ๋ฆฌํฉํ ๋ง ์ ๋ต 2: ServletContextListener๋ก ์์ ๋ก๋ฉ ์ต์ ํ
โ ServletContextListener๋?
๐ฌ ํฐ์บฃ ์๋ฒ๊ฐ ์์ํ๊ฑฐ๋ ์ข ๋ฃ๋ ๋,
๊ณตํต ์์(DB, ์ค์ ๊ฐ, DAO ๋ฑ) ์ ๋ฏธ๋ฆฌ ๋ก๋ฉํ๊ฑฐ๋ ์ ๋ฆฌํ ์ ์๊ฒ ํด์ฃผ๋ ๊ธฐ๋ฅ
โ ๊ตฌ์กฐ
@WebListener
public class AppInitListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("โ
์๋ฒ ์์: ๊ณตํต ์์ ๋ก๋ฉ ์ค...");
ServletContext ctx = sce.getServletContext();
ctx.setAttribute("appName", "JSPํฌํธ");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("๐งน ์๋ฒ ์ข
๋ฃ: ์์ ์ ๋ฆฌ ์ค...");
}
}
๐ฆ ํ์ฉ ์์
- DAO ๊ณต์ฉ ์ค์ ๊ฐ ๋ก๋ฉ
- ๊ณต์ฉ HTML๊ฒฝ๋ก, ์ ๋ก๋ ํด๋ ๊ฒฝ๋ก ์ค์
- DB ์ปค๋ฅ์ ํ ์ด๊ธฐํ
- ๋ก๊น ์ค์
โ ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ ํฌ์ธํธ
์ ๋ต | ์ค๋ช |
---|---|
์๋ฒ ์์ ์ ๊ณต์ฉ ๊ฐ์ฒด 1๋ฒ๋ง ์์ฑ | ๋งค ์์ฒญ๋ง๋ค ์๋ก ๋ง๋ค์ง ์์ ๋ฉ๋ชจ๋ฆฌ ์ ์ฝ |
ํ์ ์์ ๋ context.removeAttribute() |
์๋ช ์กฐ์ ๊ฐ๋ฅ (GC ๋์ ์ ๋) |
์๋ฒ ์ข
๋ฃ ์ ์ฐ๊ฒฐ ํด์ (contextDestroyed ) |
ํ์ผ ํธ๋ค, ๋ก๊ทธ ๋ฑ ์์ ๋์ ๋ฐฉ์ง ๊ฐ๋ฅ |
๐ ๋ฉด์ ํฌ์ธํธ ์ ๋ฆฌ
์ง๋ฌธ | ๋ชจ๋ฒ ๋ต๋ณ |
---|---|
Controller๋ ์ ์ํ๋ฅผ ๊ฐ์ง๋ฉด ์ ๋๋์? | ๋ชจ๋ ์ฌ์ฉ์๊ฐ ๊ฐ์ ์ธ์คํด์ค๋ฅผ ๊ณต์ ํ๋ฏ๋ก, ์ธ์คํด์ค ๋ณ์์ ์ฌ์ฉ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ฉด ์ถฉ๋ ๋ฐ์ํฉ๋๋ค |
DAO๋ ์ ์ฑ๊ธํค์ผ๋ก ์ค๊ณํ๋์? | ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ๊ฐ์ฒด์ด๋ฉฐ, DB ์ฐ๊ฒฐ์ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๊ธฐ ์ํจ์ ๋๋ค |
ServletContextListener๋ ์ ์ฐ๋์? | ์๋ฒ ์์/์ข ๋ฃ ์์ ์ ํ์ํ ์์(DB, ์ค์ ๋ฑ)์ ๋ก๋ฉํ๊ณ , ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ ์ฝํ๊ธฐ ์ํด์์ ๋๋ค |
GC๊ฐ Controller ๊ตฌ์กฐ์ ์ํฅ์ ๋ฏธ์น๋์? | ์ํ๊ฐ ์๋ Controller๋ ๋ฉ๋ชจ๋ฆฌ ๋์ ๊ฐ๋ฅ์ฑ์ด ํฌ๊ธฐ ๋๋ฌธ์ ์ํ ์๋ ๊ตฌ์กฐ๊ฐ GC์ ์ ๋ฆฌํฉ๋๋ค |
โ ๋ง๋ฌด๋ฆฌ ์์ฝํ
ํญ๋ชฉ | ๊ฐ์ ์ ๋ต | ๋ฉ๋ชจ๋ฆฌ ํจ๊ณผ |
---|---|---|
Controller | ์ํ ์๋ ๊ตฌ์กฐ | Thread-safe, GC ์๊ฑฐ ์ฌ์ |
Service | Stateless ๊ตฌ์กฐ | ์ฌ์ฌ์ฉ ๊ฐ๋ฅ, ๋ฉ๋ชจ๋ฆฌ ๋์ ์์ |
DAO | ์ฑ๊ธํค + ์ปค๋ฅ์ ํ + try-with-resources | ๋ฆฌ์์ค ์์ ์ฑ ์ต๊ณ |
ServletContextListener | ์๋ฒ ์์ ์ ์์ 1ํ ๋ก๋ฉ | ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น โ, ์ด๊ธฐํ ๋น์ฉ โ |
โ PART 8.2 Spring MVC vs JSP ๋ชจ๋ธ2 ๊ตฌ์กฐ ๋น๊ต + ํ๊ณ
โ์ JSP Model2์์ Spring MVC๋ก ๋์ด๊ฐ์ผ ํ ๊น?โ
๐ข 1๋จ๊ณ. ๊ธฐ๋ณธ ๊ฐ๋ ๋ถํฐ ์์ โ Model2๋?
๐ฌ JSP Model2๋ โ์๋ธ๋ฆฟ์ด ์ปจํธ๋กค๋ฌ ์ญํ โ์ ํ๊ณ ,
JSP๋ ๋ทฐ(view) ์ญํ ๋ง ๋งก๋ ๊ตฌ์กฐ์ผ.
[์ฌ์ฉ์ ์์ฒญ] โ Controller(Servlet) โ Service โ DAO โ JSP(View)
๐ ์ด ๊ตฌ์กฐ๋ง์ผ๋ก๋ MVC ํจํด์ ๋์ง๋ง, Spring์ฒ๋ผ ์๋ํ, ์ค์ ์ฃผ์ ์ ์์!
๐ Spring MVC๋ ์ด๋ป๊ฒ ๋ค๋ฅผ๊น?
โ Spring MVC ๊ตฌ์กฐ (IoC + DI + AOP)
[DispatcherServlet] โ [Controller] โ [Service] โ [DAO]
โ โ
[IoC Container] (๊ฐ์ฒด ์๋ ๊ด๋ฆฌ)
- DispatcherServlet: ์์ฒญ์ ๋ฐ๊ณ ๋ผ์ฐํ
- IoC Container: ํ์ํ ๊ฐ์ฒด๋ฅผ ์๋์ผ๋ก ๋ง๋ค์ด์ ๋ฃ์ด์ค (DI)
- AOP: ๋ก๊ทธ, ํธ๋์ญ์ ์ฒ๋ฆฌ ๋ฑ์ ํต์ฌ ์ฝ๋ ๋ฐ๊นฅ์์ ์ฒ๋ฆฌ
โ๏ธ 2๋จ๊ณ. Spring์ IoC / DI / AOP ๊ตฌ์กฐ๊ฐ ๋ฉ๋ชจ๋ฆฌ์ ๋ฏธ์น๋ ๊ธ์ ์ ์ํฅ
โ IoC (์ ์ด์ ์ญ์ )๋?
๊ฐ์ฒด๋ฅผ ์ง์ ๋ง๋ค์ง ์๊ณ , Spring์ด ๋์ ๋ง๋ค์ด์ฃผ๋ ๋ฐฉ์
// Model2 ๋ฐฉ์
MemberService service = new MemberService(); // ์ง์ new โ
// Spring ๋ฐฉ์
@Autowired
MemberService service; // โจ ์๋ ์ฃผ์
(DI)
โ DI (์์กด์ฑ ์ฃผ์ )์ผ๋ก ์ป๋ ์ด์
ํญ๋ชฉ | ์ค๋ช | ๋ฉ๋ชจ๋ฆฌ ํจ๊ณผ |
---|---|---|
์ฌ์ฌ์ฉ์ฑ โ | ํ๋ ๋ง๋ ๊ฐ์ฒด๋ฅผ ์ฌ๋ฌ ํด๋์ค์ ์ฃผ์ | ์ค๋ณต ๊ฐ์ฒด ์์ฑ โ |
ํ ์คํธ ์ฌ์ | Mock ๊ฐ์ฒด๋ ์ฝ๊ฒ ์ฃผ์ ๊ฐ๋ฅ | ์ ์ง๋ณด์ ๋น์ฉ โ |
GC ์ ๋ฆฌ | ๊ฐ์ฒด ์๋ช ์ฃผ๊ธฐ๋ฅผ IoC๊ฐ ๊ด๋ฆฌ โ ํ์ ์์ผ๋ฉด GC๋ก ์์ฐ ์ ๋ฆฌ๋จ โ | ย |
โ AOP (๊ด์ ์งํฅ ํ๋ก๊ทธ๋๋ฐ)
๋ก๊ทธ ์ถ๋ ฅ, ํธ๋์ญ์ , ๋ณด์ ์ฒ๋ฆฌ ๊ฐ์ ๊ฑธ ๋น์ฆ๋์ค ๋ก์ง ๋ฐ๊นฅ์์ ์๋ ์ฒ๋ฆฌ
// AOP ๋ฏธ์ฌ์ฉ ์
log.info("์์");
memberService.register(member);
log.info("์ข
๋ฃ");
// AOP ์ฌ์ฉ ์
@Loggable
public void register(Member member) {
...
}
๐ง ํต์ฌ:
- ์ฝ๋ ์ค๋ณต ์ ๊ฑฐ โ ์ฝ๋๋ โ
- ๊ฐ์ฒด ์ฒ๋ฆฌ ๋จ์ํ โ ๋ฉ๋ชจ๋ฆฌ ํ ๋น โ
- ํ์ ์๋ ๋ก์ง์ ์กฐ๊ฑด๋ถ๋ก ๋ถ๋ฆฌ ๊ฐ๋ฅ
๐ซ 3๋จ๊ณ. JSP Model2 ๊ตฌ์กฐ์์ DI ๋ถ๊ฐ๋ฅํ ๋ณ๋ชฉ ์ง์
โ ๋ฌธ์ 1: ์ง์ new ์์ฑ
public class BoardController extends HttpServlet {
private BoardService service = new BoardService(); // โ ํญ์ new
}
๋ฌธ์ ์ | ์ค๋ช |
---|---|
๊ฐ์ฒด ์ฌ์ฌ์ฉ ๋ถ๊ฐ | ์์ฒญ๋ง๋ค ์๋ก์ด ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ฉด GC ๋ถ๋ด โ |
ํ ์คํธ ์ด๋ ค์ | ๋ค๋ฅธ ๊ฐ์ฒด๋ฅผ ๋ฃ์ ์ ์์ (Mock ๋ถ๊ฐ) |
์ํ ์์กด ๋ฐฉ์ง ๋ถ๊ฐ | ์์กด์ฑ ๊ด๊ณ๊ฐ ๊ผฌ์ด๋ฉด ํด๊ฒฐ ์ด๋ ค์ |
โ ๋ฌธ์ 2: ์ํ ์๋ Controller ์ค๊ณ ์ํ
@WebServlet("/board/write")
public class WriteController extends HttpServlet {
private List<String> tempList = new ArrayList<>(); // โ ๊ณต์ ๋จ
}
- ๋ชจ๋ ์ฌ์ฉ์์๊ฒ ๊ณต์ ๋๋ ์ธ์คํด์ค ๋ณ์ โ Thread-safe X
- ๋ฉ๋ชจ๋ฆฌ ๋์ + ๋ฐ์ดํฐ ์ถฉ๋ ์ํ
โ ๋ฌธ์ 3: ๊ณตํต ์ฒ๋ฆฌ(AOP ๋ถ๊ฐ)
๊ธฐ๋ฅ | JSP Model2์์ ๋ถํธํ ์ด์ |
---|---|
๋ก๊ทธ์ธ ์ฒดํฌ | ์ปจํธ๋กค๋ฌ๋ง๋ค ์ฝ๋ ์ฝ์ ํด์ผ ํจ |
ํธ๋์ญ์ ์ฒ๋ฆฌ | ๋ชจ๋ DAO์ try-catch ๋ฐ๋ณต |
๋ก๊น | ์ค๋ณต ์ฝ๋ ๋ฐ์, ์ฑ๋ฅ ์ ํ |
โ Spring์์๋ AOP๋ก ํ ๋ฒ์ ์ฒ๋ฆฌ ๊ฐ๋ฅ โ ์ฑ๋ฅ + ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ
๐ 4๋จ๊ณ. ๋ฉด์ ํฌ์ธํธ ์ ๋ฆฌ
์ง๋ฌธ | ๋ชจ๋ฒ ๋ต๋ณ ์์ฝ |
---|---|
JSP Model2์์ DI๊ฐ ์ด๋ ต๋ค๋ ๊ฑด ๋ฌด์จ ๋ป์ธ๊ฐ์? | ๊ฐ์ฒด๋ฅผ new๋ก ์ง์ ๋ง๋ค๊ธฐ ๋๋ฌธ์ IoC ์ปจํ ์ด๋๊ฐ ์์ด์ ์์กด์ฑ ์ฃผ์ ์ด ๋ถ๊ฐ๋ฅํฉ๋๋ค |
Spring์ด ๋ฉ๋ชจ๋ฆฌ์ ์ผ๋ก ๋ ์ ๋ฆฌํ ์ด์ ๋? | IoC ์ปจํ ์ด๋๊ฐ ๊ฐ์ฒด๋ฅผ ํ๋๋ง ์์ฑํด ๊ณต์ ํ๊ณ , ๋ถํ์ํ ๊ฐ์ฒด ์์ฑ์ ์ค์ฌ GC ํจ์จ์ด ๋์ต๋๋ค |
JSP Model2๋ ์ด๋ค ๊ตฌ์กฐ์ ํ๊ณ๊ฐ ์๋์? | ์ฝ๋ ์ฌ์ฌ์ฉ์ฑ ๋ถ์กฑ, ํ ์คํธ ์ด๋ ค์, ๊ณตํต ์ฒ๋ฆฌ ์ด๋ ค์, GC ๋ถ๋ด ์ฆ๊ฐ ๋ฑ์ด ์์ต๋๋ค |
AOP๊ฐ ์ ์ฑ๋ฅ์ ์ข์๊ฐ์? | ๋ก๊ทธ, ๋ณด์, ํธ๋์ญ์ ๊ฐ์ ๋นํต์ฌ ๋ก์ง์ ๋ถ๋ฆฌํด ์ฝ๋๋๊ณผ ๋ฉ๋ชจ๋ฆฌ ๋ถ๋ด์ ์ค์ฌ์ค๋๋ค |
โ ๋ง๋ฌด๋ฆฌ ์์ฝํ
ํญ๋ชฉ | JSP Model2 | Spring MVC |
---|---|---|
๊ฐ์ฒด ์์ฑ | ์ง์ new | IoC๊ฐ ์๋ ์์ฑ |
DI(์์กด์ฑ ์ฃผ์ ) | ๋ถ๊ฐ | ์๋ ์ฃผ์ (@Autowired) |
AOP ์ ์ฉ | ์๋, ๋ณต์ก | ๊ฐ๋จํ ์ ์ฉ (๋ก๊ทธ, ๋ณด์, ํธ๋์ญ์ ๋ถ๋ฆฌ) |
๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ | ์ง์ ๊ด๋ฆฌ โ ๋์ ์ํ | Spring์ด ์๋ช ์ฃผ๊ธฐ ์๋ ๊ด๋ฆฌ โ GC ํจ์จ โ |
ํ ์คํธ ์ฉ์ด์ฑ | ๋ฎ์ | ๋์ (Mock ์ฃผ์ ๊ฐ๋ฅ) |