IT story/Spring

[Spring 강의] L03 Controller2

jason719 2016. 12. 14. 19:10

2016. 12. 14. (Wed)

[Spring 강의] L03 Controller2

오늘은 기존에 model2로 만든 게시판을 Spring으로 변환하는 수업을 했다. 

강사가 워낙 정신없이 해서 수업내용 따라 적은거 밖에 없지만.. 

model2에서 spring으로 변환하는 방법을 알아보자.

1. 새로운 프로젝트를 아래와 같이 생성하고 이클립스에서 model2 내용을 복사해 왔다.


2. com 하위에 spring package를 만들고 model2 내용을 일부 수정하여 복사해 온다.

자세한 내용은 파일별로 알아보도록 하자.


첫 번째로 controller이다. 자세한 내용은 아래의 코드와 주석을 살펴보자.

spring - controller 

ex) MemberController.java

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package com.spring.controller;
 
 
import java.util.List;
 
 
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
 
import com.spring.dao.MemberDao;
import com.spring.vo.MemberVo;
import com.spring.vo.Paging;
 
 
@Controller
@RequestMapping("/member/*")
public class MemberController {
 
 
    MemberDao dao;
 
 
    @RequestMapping("list.do")
    public String list(Model model, Paging paging) {
        dao = MemberDao.getInstance();
        int totalCount = dao.listCount();
        paging.setTotalCount(totalCount);
        List<MemberVo> memList = dao.selectAllMember(paging);
        model.addAttribute("memList", memList);
        return "member/MemberList";
    }
 
 
    @RequestMapping(value = "insert.do", method = RequestMethod.GET)
    public String insertForm(Model model) {
        dao = MemberDao.getInstance();
        int maxNum = dao.selectMaxNum();
        model.addAttribute("maxNum", maxNum);        
        return "member/MemberAddForm";
    }//doGet()
 
 
    @RequestMapping(value = "insert.do", method = RequestMethod.POST)
    public String insert(MemberVo member, Model model) {
        System.out.println("id : " + member.getId());
        //post 방식으로 호출한 페이지는 새로고침 공격을 막기 위해 꼭 redirect로 url을 변경해야 한다.
        dao = MemberDao.getInstance();
        int insert = 0;
        boolean checkId = true;
        checkId = dao.selectId(member.getId());
        if(!checkId){
            insert = dao.insertMember(member);
        }
        model.addAttribute("insert", insert);
        model.addAttribute("checkId", checkId);
        
        String url = (insert>0)?"list.do":"insert.do";
        return "redirect:"+url;
    }//doPost()
 
 
 
    @RequestMapping(value = "update.do", method = RequestMethod.GET)
    public String updateForm(@RequestParam("num"int num, Model model) {
        //detail과 동일 -> 꼭 num이 넘어와야한다.
        dao = MemberDao.getInstance();
        MemberVo member = dao.detailMember(num);
        model.addAttribute("mem", member);
        return "member/MemberUpdateForm";
    }
 
 
    @RequestMapping(value = "update.do", method = RequestMethod.POST)
    public String update(MemberVo member, Model model) {
        dao = MemberDao.getInstance();
        int update = 0;
        update = dao.updateMember(member);
        String url = (update>0)?"list.do":"update.do";
        model.addAttribute("update", update);
        return "redirect:"+url;
    }
 
 
    @RequestMapping("delete.do")
    public String delete(@RequestParam("num"int num) {
        dao = MemberDao.getInstance();
        int delete = 0;
        delete = dao.deleteMember(num);
        return "redirect:list.do?delete="+delete;
    }
}
cs

두 번째로는 DAO를 살펴보자

DAO는 model2와 거의 동일하다.. (MySQL을 이용해서 쿼리가 일부 수정이 필요하다)

spring - dao

ex) MemberDao.java

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
package com.spring.dao;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
 
import com.spring.vo.MemberVo;
import com.spring.vo.Paging;
 
import util.DBManager;
 
public class MemberDao {
    // 쿼리실행!!
    Connection conn = null;
    Statement stmt = null;
    PreparedStatement pstmt = null;
    ResultSet rs = null;
 
    private static MemberDao instance = new MemberDao();
 
    // bean과 닮았다.
    public static MemberDao getInstance() {
        return instance;
    }
 
    public MemberVo detailMember(int num) {
        String sql = "select * from member where num = ?";
        MemberVo mvo = new MemberVo();
        try {
            conn = DBManager.getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, num);
            rs = pstmt.executeQuery();
            if (rs.next()) {
                mvo.setNum(rs.getInt("num"));
                mvo.setId(rs.getString("id"));
                mvo.setPwd(rs.getString("pwd"));
                mvo.setName(rs.getString("name"));
                mvo.setEmail(rs.getString("email"));
                mvo.setPhone(rs.getString("phone"));
                mvo.setIndate(rs.getString("indate"));
                mvo.setAdmin(rs.getString("admin").charAt(0));
            }
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        } finally {
            DBManager.close(rs, pstmt, conn);
        }
        return mvo;
    }
    public int listCount() {
        String sql = "SELECT COUNT(*) as count FROM MEMBER";
        int count = 0;
        try{
            conn = DBManager.getConnection();
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            if(rs.next()){
                count = rs.getInt("count");
            }
        }catch(SQLException e){
            e.printStackTrace();
        } finally {
            DBManager.close(rs, stmt, conn);
        }
        return count;
    }
 
    
    public List<MemberVo> selectAllMember(Paging paging) {
        String sql ="select c.* from ("
                + "select @RNUM := @RNUM+1 AS  ROWNUM, b.* from ("
                + "select member.* from member order by num desc)b, ("
                + "SELECT @RNUM :=0)R)c where ROWNUM between ? AND ?"
        List<MemberVo> list = new ArrayList<MemberVo>();
        try {
            conn = DBManager.getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, paging.getStartNum());
            pstmt.setInt(2, paging.getEndNum());
            rs = pstmt.executeQuery();
            System.out.println("server 접속");
            while (rs.next()) {
                MemberVo mvo = new MemberVo();
                mvo.setNum(rs.getInt("num"));
                mvo.setId(rs.getString("id"));
                mvo.setPwd(rs.getString("pwd"));
                mvo.setName(rs.getString("name"));
                mvo.setEmail(rs.getString("email"));
                mvo.setPhone(rs.getString("phone"));
                mvo.setIndate(rs.getString("indate"));
                mvo.setAdmin(rs.getString("admin").charAt(0));
                list.add(mvo);
            }
 
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            DBManager.close(rs, pstmt, conn);
        }
        return list;
    }
 
    public int deleteMember(int num) {
        int delete = 0;
        String sql = "delete from member where num = ?";
        try {
            conn = DBManager.getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, num);
            delete = pstmt.executeUpdate();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            DBManager.close(rs, pstmt, conn);
        }
        return delete;
 
    }
 
    public int updateMember(MemberVo member) {
        String sql = "update member set name=?, email=?, pwd=? phone=?, admin=? where num=?";
        int update = 0;
 
        try {
            conn = DBManager.getConnection();
            pstmt = conn.prepareStatement(sql);
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        } finally {
            DBManager.close(rs, pstmt, conn);
        }
        return update;
    }
 
    public int selectMaxNum() {
        int maxNum = 0;
        String sql = "select MAX(num) as MAX_NUM from member";
        try {
            conn = DBManager.getConnection();
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            if (rs.next()) {
                maxNum = (rs.getInt("MAX_NUM"));
            }
        } catch (Exception e) {
            // TODO: handle exception
        } finally {
            DBManager.close(rs, stmt, conn);
        }
        return maxNum;
    }
 
    public boolean selectId(String id) {
        boolean idFlag = false;
        String sql = "select * from member where id = ?";
        try {
            conn = DBManager.getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, id);
            rs = pstmt.executeQuery();
            if (rs.next()) {
                idFlag = true;
            }
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        } finally {
            DBManager.close(rs, pstmt, conn);
        }
        return idFlag;
    }
 
    public int insertMember(MemberVo mvo) {
        int insert = 0;
        String sql = "insert into member (num,id,pwd,name,email,phone,admin) values (?,?,?,?,?,?,?)";
        try {
            conn = DBManager.getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, mvo.getNum());
            pstmt.setString(2, mvo.getId());
            pstmt.setString(3, mvo.getPwd());
            pstmt.setString(4, mvo.getName());
            pstmt.setString(5, mvo.getEmail());
            pstmt.setString(6, mvo.getPhone());
            pstmt.setString(7, mvo.getAdmin()+"");
            
            insert = pstmt.executeUpdate();
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        } finally {
            DBManager.close(rs, pstmt, conn);
        }
        return insert;
    }
 
    public MemberVo login(String id, String pwd) {
        String sql = "select num, id, name, admin from member where id = ? and pwd = ?";
        MemberVo mvo = null;
        try {
            conn = DBManager.getConnection();
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, id);
            pstmt.setString(2, pwd);
            rs = pstmt.executeQuery();
            if (rs.next()) {
                mvo = new MemberVo();
                mvo.setNum(rs.getInt("num"));
                mvo.setId(rs.getString("id"));
                mvo.setName(rs.getString("name"));
                mvo.setAdmin(rs.getString("admin").charAt(0));
            }
            
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        } finally {
            DBManager.close(rs, pstmt, conn);
        }
        
        return mvo;
    }
 
    public int getAllCount() {
        String sql = "SELECT COUNT(*) AS count from member";
        int count = 0;
        try {
            conn = DBManager.getConnection();
            stmt = conn.createStatement();
            rs = stmt.executeQuery(sql);
            if (rs.next()) {
                count = rs.getInt("count");
            } 
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        } finally {
            DBManager.close(rs, stmt, conn);
        }
        return count;
    }
 
}
 
cs

HomeController에서 Paging의 RequestMapping을 해줘야 출력이 된다.

ex) HomeController.java

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
34
35
36
37
38
39
40
41
42
43
package com.spring.l03_controller2;
 
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
 
/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
    
    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
    
    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);
        
        Date date = new Date();
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale);
        
        String formattedDate = dateFormat.format(date);
        
        model.addAttribute("serverTime", formattedDate );
        
        return "home";
    }
    @RequestMapping("/paging/paging")
    public void paging() {
        
    }
}
 
cs

Vo의 MemberVo와 Paging의 내용도 살펴보자

ex) MemberVo.java

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package com.spring.vo;
 
//Member는 데이터베이스의 Member table과 매칭 
public class MemberVo {
    private int num;
    private String id;
    private String pwd;
    private String name;
    private String email;
    private String phone;
    private char admin;
    private String indate;
    
    public String getIndate() {
        return indate;
    }
    public void setIndate(String indate) {
        this.indate = indate;
    }
    public int getNum() {
        return num;
    }
    public void setNum(int num) {
        this.num = num;
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getPwd() {
        return pwd;
    }
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
    public char getAdmin() {
        return admin;
    }
    public void setAdmin(char admin) {
        this.admin = admin;
    }
    @Override
    public String toString() {
        // TODO Auto-generated method stub
        return super.toString();
    }
    
    
}
 
cs

ex) Paging.java

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package com.spring.vo;
 
 
public class Paging {
    private int page=1//현재 페이지 (set) 
    private int totalCount; //row의 전체 수 (set)
    private int beginPage; //출력 시작
    private int endPage;    //출력 끝
    private int displayRow = 10//한페이지에 몇개의 로우 (선택 set)
    private int displayPage = 10;    //한페이지에 몇개의 페이지(선택 set)
    boolean prev; //prev 버튼이 보일건지 안보일건지
    boolean next; //next 버튼이 보일건지 안보일건지
    int startNum;
    int endNum;
 
 
    public int getStartNum() {return startNum;}
    public int getEndNum() {return endNum;}
    public int getPage() {return page;}
    public void setPage(int page) {this.page = page;}
    public int getTotalCount() {return totalCount;}
    public void setTotalCount(int totalCount) {
        //setTotalCount()를 꼭 호출해야 paging이 되기 때문에 
        //paging()함수를 setTotalCount()를 호출했을때 자동으로 호출되게 한다.
        this.totalCount = totalCount;
        paging();
    }
    public int getDisplayRow() {return displayRow;}
    public void setDisplayRow(int displayRow) {this.displayRow = displayRow;}
    public int getDisplayPage() {return displayPage;}
    public void setDisplayPage(int displayPage) {    this.displayPage = displayPage;}
    public int getBeginPage() {return beginPage;}
    public int getEndPage() {return endPage;}
    public boolean isPrev() {return prev;}
    public boolean isNext() {return next;}
    
    private void paging(){
        startNum = (page-1)*displayRow+1;
        endNum = page*displayRow;
        //prev,next,beginPage,endPage 를 계산해서 만든다.
        // 2+(10-1) =11, 11/10 = 1, 1*10 = 10 
        // 10+(10-1) = 19, 19/10 = 1, 1*10 = 10
        // 11+(10-1) = 20  20/10 = 2, 2*10 =20
        // 20+(10-1) = 29  29/10 = 2, 2*10 =20
        // 111+(10-1) = 120  120/10 = 12, 12*10 =120
 
 
        // (2+9)/10 * 10
        endPage = ((page+(displayPage-1))/displayPage)*displayPage;
        //1/10 0.1 (올림) 1
        //Math.ceil 올림
        //endPage = ((int)Math.ceil(page/(double)displayPage))*displayPage;
        System.out.println("endPage:"+endPage);
        
        beginPage= endPage-(displayPage-1);
        System.out.println("beginPage:"+beginPage);
        
        //글 32개 
        //32/10.0 3.2 (올림) (int)4.0  4페이지
        // 2 =? 2/10 
        int totalPage =(int)Math.ceil(totalCount/(double)displayRow); 
        
        if(totalPage<endPage){
            endPage = totalPage;
            next=false;
        }else{
            next=true;
        }
        prev=(beginPage==1)?false:true;//page 가 11이상때만 나온다.
        System.out.println("endPage:"+endPage);
        System.out.println("totalPage:"+totalPage);
        System.out.println("totalCount:"+totalCount);
    }
}
cs

위의 코드를 사용하려면 servlet-context.xml에 입력해줘야한다!

ex) servlet-context.xml 

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
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:beans="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
 
    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
    
    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />
 
    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />
 
    <!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
    <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>
    
    <context:component-scan base-package="com.spring.l03_controller2" />
    <context:component-scan base-package="com.spring.controller" />
    
    
</beans:beans>
 
cs

Spring 수업을 시작하면서 모든 내용을 업로드하는 것은 비효율적이라는 생각이 든다.

그래서 다음 포스트부터는 중요한 요점만 올리도록 해야겠다...

Member List를 출력하기 위해 views - member forder에 MemberList.jsp를 생성해보자!

이것도 model2에서 복사해온것인데 jsp:include에서 오류가 발생한다. 그 부분만 c:import & c:param으로 수정한다.

ex) MemberList.jsp

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <%-- <jsp:include page="/layout/header.jsp" /> --%>
    <table border="1">
        <tr>
            <th>num</th>
            <th>id</th>
            <th>pwd</th>
            <th>name</th>
            <th>email</th>
            <th>phone</th>
            <th>indate</th>
            <th>admin</th>
            <th>수정</th>
            <th>삭제</th>
        </tr>
 
        <!-- el태그에서 변수는 내장객체의 이름이다. page> (request,session, application) -->
        <%
            //request.getAttribute("memList");
            //memList는 request 내장 객체에 있는 변수다.
        %>
        <c:forEach items="${memList}" var="mem">
            <tr>
                <td>${mem.num }</td>
                <td>${mem.id }</td>
                <td>${mem.pwd }</td>
                <td>${mem.name }</td>
                <td>${mem.email }</td>
                <td>${mem.phone }</td>
                <td>${mem.indate }</td>
                <td>${mem.admin }</td>
                <td><a href="./memUpdateForm.do?num=${mem.num }">수정</a></td>    
                <!-- MemberUpdateController.java -> MemberDao.detailMember(int num) -> 수정 성공시 -> memList.do -->            
                <td><a href="./memDelete.do?num=${mem.num }">삭제</a></td>
                <!-- MemberDeleteController.java -> MemberDao.deleteMember(int num) -> 삭제 성공시 -> memList.do -->
            </tr>
        </c:forEach>
    </table>
    <c:import url="/paging/paging">
        <c:param value="/member/list.do" name="action"/>
        <c:param value="${paging.page }" name="page"/>
        <c:param value="${paging.beginPage }" name="begin"/>
        <c:param value="${paging.endPage }" name="end"/>
        <c:param value="${paging.prev }" name="prev"/>
        <c:param value="${paging.next }" name="next"/>
    </c:import>
    <p><strong><a href="insert.do">회원가입</a></strong></p>
</body>
</html>
cs

출력내용은 아래와 같다.

1. Home.jsp 출력화면 

jsp 때의 index.jsp라고 생각하면 된다.

2. MemberList.jsp 출력화면

워낙 수업을 번갯불에 콩구워먹듯 빨리 빨리 진해해서 어떤 원리인지 정확히 파악하지는 못했지만,

model2 수업 때처럼 잘 출력되는 것을 확인할 수 있다.

페이징도 잘 돌아가는 것을 볼 수 있다!!


지금까지는 프로젝트의 모든 내용을 올렸었는데, Spring 들어와서부터는 비효율적이라는 생각이 든다.

내용도 너무 많고, 그러다보니 정작 중요한 부분이 강조 되지 못하는 거 같아 내일부터는 중요한 포인트만

정리 해야겠다! 이 블로그는 공개로 작성 중에 있으나 새롭게 IT수업을 받기 시작하면서 복습 효과를 위해

개인적인 복습공간으로 활용중이다보니 정보 검색에는 부적합 할 수 있음을 양해 바란다.