20220524 복습

2022 - 0524 - 복습


package com.hanulso.controller; 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() { return "index"; } }


package com.hanulso.domain; import java.sql.Date; //util.Date도 된다??? (Date regdate) import lombok.Data; @Data public class NoticeVO { private int bno; private String title; private String content; private String writer; private Date regdate; private int hits; }

< Spring 기초 >




>>> pom.xml
12라인 -> 5.0.7
64라인 -> 1.2.17
116라인 -> 4.12
139라인 -> 3.5.1
141라인 -> 1.8
142라인 -> 1.8
-----------------------------------------------------------------------------------------------------
>>> root-context.xml

<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">

     <property name="driverClassName"
          value="net.sf.log4jdbc.sql.jdbcapi.DriverSpy"></property>
     <property name="jdbcUrl"
          value="jdbc:log4jdbc:oracle:thin:@localhost:1521:XE"></property>
     <property name="username" value="db53"></property>
     <property name="password" value="123456"></property>

</bean>

<!-- HikariCP configuration -->
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource"
     destroy-method="close">
          <constructor-arg ref="hikariConfig" />
</bean>

<bean id="sqlSessionFactory"
     class="org.mybatis.spring.SqlSessionFactoryBean">
          <property name="dataSource" ref="dataSource">
</bean>

<mybatis-spring:scan
     base-package="com.jslhrd.mapper" />

<context:component-scan
     base-package="com.jslhrd.service">

-----------------------------------------------------------------------------------------------------
>>> buildpath
mysql-connector-java-8.0.28.jar
ojdbc8.jar
-----------------------------------------------------------------------------------------------------
>>>src/main/resources
log4jdbc.log4j2.properties 파일 생성
log4jdbc.spylogdelegator.name=net.sf.log4jdbc.log.slf4j.Slf4jSpyLogDelegator 내용입력
-----------------------------------------------------------------------------------------------------
>>>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
@Log4j

@Setter(onMethod_ = @Autowired)
@Select("select sysdate from dual")

@Service // 계층 구조상 주로 비즈니스 영역을 담당하는 객체임을 표시하기 위해 사용함.
@Log4j
@AllArgsConstructor // 생성자를 만들고 자동으로 주입함.

<BoardController.java>
@Controller
@Log4j
@RequestMapping("/board/*")
@AllArgsConstructor

<BoardControllerTests.java>
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration({"file:src/main/webapp/WEB-INF/spring/root-context.xml",
               "file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml"})
@Log4j

>>>Tomcat 더블클릭 - Modules - Edit - controller 부분 지우기
-----------------------------------------------------------------------------------------------------
P.173
>>>Oracle 테이블

사용자 추가 후

system/123456

db53/123456


create user db53 identified by 123456;
grant connect,resource to db53;
grant create view to db53;

create sequence seq_board;

create table tbl_board(
bno number(10,0),
title varchar2(200) not null,
content varchar2(2000) not null,
writer varchar2(50) not null,
regdate date default sysdate,
updatedate date default sysdate
);

create table tbl_member(
userid varchar2(50) not null primary key,
userpw varchar2(100) not null,
username varchar2(100) not null,
regdate date default sysdate,
updatedate date default sysdate,
enabled char(1) default '1');

create table tbl_member_auth(
userid varchar2(50) not null,
auth varchar2(50) not null,
constraint fk_member_auth foreign key(userid) references tbl_member(userid)
);

alter table tbl_board add constraint pk_board primary key(bno);

insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user00');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user01');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user02');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user03');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user04');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user05');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user06');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user07');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user08');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user09');
insert into tbl_board(bno,title,content,writer) values(seq_board.nextval,'테스트 제목','테스트 내용','user10');

-----------------------------------------------------------------------------------------------------
>>> BoardMapper.xml (@Select 어노테이션을 써도 되지만, 쿼리문이 복잡해질 경우 xml 파일로 관리하는게 유리하다 !!!)

src/main/resources -> com 폴더 -> jslhrd 폴더 -> mapper 폴더 생성 후, 그 안에 BoardMapper.xml 파일 생성
(com.jslhrd.mapper 패키지 명과 동일한 틀로)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jslhrd.mapper.BoardMapper">

     <!-- 부등호 들어가면 CDATA 처리 !!! -->

     <select id="getList" resultType="com.jslhrd.domain.BoardVO">
          <![CDATA[
               select * from tbl_board where bno > 0
          ]]>
     </select>

     <insert id="insert">
          insert into tbl_board(bno,title,content,writer) values(seq_board.nextval, #{title}, #{content}, #{writer})
     </insert>

     <insert id="insertSelectKey">
          <selectKey keyProperty="bno" order="BEFORE" resultType="long">
               select seq_board.nextval from dual
          </selectKey>
          insert into tbl_board(bno,title,content,writer) values(#{bno}, #{title}, #{content}, #{writer})
     </insert>

     <select id="read" resultType="com.jslhrd.domain.BoardVO">
          select * from tbl_board where bno = #{bno}
     </select>

     <update id="update">
          update tbl_board
          set title=#{title},
          content=#{content},
          writer=#{writer},
           updateDate=sysdate
          where bno=#{bno}
     </update>

     <delete id="delete">
          delete from tbl_board where bno=#{bno}
     </delete>

</mapper>

-----------------------------------------------------------------------------------------------------
src/main/resources -> com 폴더 -> jslhrd 폴더 -> mapper 폴더 생성 후, 그 안에 TimeMapper.xml 파일 생성
(com.jslhrd.mapper 패키지 명과 동일한 틀로)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jslhrd.mapper.TimeMapper">
     <select id="getTime2" resultType="string">
          select sysdate from dual
     </select>
</mapper>

-------------------------------------------------------------------------------------- src/main/resources -> com 폴더 -> jslhrd 폴더 -> mapper 폴더 생성 후, 그 안에 MemberMapper.xml 파일 생성
(com.jslhrd.mapper 패키지 명과 동일한 틀로)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
     PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jslhrd.mapper.MemberMapper">

     <resultMap type="com.jslhrd.domain.MemberVO" id="memberMap">
          <id property="userid" column="userid" />
          <result property="userid" column="userid" />
          <result property="userpw" column="userpw" />
          <result property="userName" column="username" />
          <result property="regDate" column="regdate" />
          <result property="updateDate" column="updatedate" />
          <collection property="authList" resultMap="authMap">
          </collection>
     </resultMap> <!-- 여러개의 데이터를 처리하는 경우 1:N의 결과를 처리할 수 있는 resultMap 태그 사용 -->

     <resultMap type="com.jslhrd.domain.AuthVO" id="authMap">
          <result property="userid" column="userid" />
          <result property="auth" column="auth" />
     </resultMap>

     <select id="read" resultMap="memberMap"> <!-- mem 테이블과 auth 테이블을 쪼인하여 userid에 해당하는 항목들을 가져옴. -->
          SELECT
               mem.userid, userpw, username, enabled, regdate, updatedate, auth
          FROM
               tbl_member mem LEFT OUTER JOIN tbl_member_auth auth on mem.userid = auth.userid where mem.userid = #{userid}
     </select>

</mapper>

--------------------------------------------------------------------------------------
>>> web.xml (인코딩 & Security)

<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- The definition of the Root Spring Container shared by all Servlets and Filters --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/root-context.xml /WEB-INF/spring/security-context.xml <!-- security-context.xml을 로딩하도록 빈 설정 --> </param-value> </context-param> <!-- Creates the Spring Container shared by all Servlets and Filters --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Processes application requests --> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <!-- 한글깨짐 현상 처리 시작 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter </filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 한글깨짐 현상 처리 끝 --> <!-- Spring Security 시작 --> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy </filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- Spring Security 끝 --> </web-app>
--------------------------------------------------------------------------------------
>>> Modal 코드

<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
     <div class="modal-dialog">
          <div class="modal-content">
               <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                    <h4 class="modal-title" id="myModalLabel">Modal title</h4>
               </div>
               <div class="modal-body">
(modal)
               </div>
               <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
                    <button type="button" class="btn btn-primary">Save changes</button>
               </div>
          </div>
          <!-- /.modal-content -->
     </div>
     <!-- /.modal-dialog -->
</div>
<!-- /.modal -->


--------------------------------------------------------------------------------------
>>> security-context.xml
(WEB-INF / spring 폴더 내에 생성)
(Namespaces 에서 security 항목 체크 !!!)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- 5.0버전은 에러가 발생 버그 때문에 지우기 --> <bean id="customAccessDenied" class="com.jslhrd.security.CustomAccessDeniedHandler"></bean> <bean id="customLoginSuccess" class="com.jslhrd.security.CustomLoginSuccessHandler"></bean> <!-- <bean id="customPasswordEncoder" class="com.jslhrd.security.CustomNoOpPasswordEncoder"></bean> --> <bean id="bcryptPasswordEndcoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean> <bean id="customUserDetailsService" class="com.jslhrd.security.CustomUserDetailsService"></bean> <security:http auto-config="true" use-expressions="true"> <security:intercept-url pattern="/sample/all" access="permitAll" /> <security:intercept-url pattern="/sample/member" access="hasRole('ROLE_MEMBER')" /> <security:intercept-url pattern="/sample/admin" access="hasRole('ROLE_ADMIN')" /> <security:intercept-url pattern="/board/list" access="hasRole('ROLE_MEMBER')" /> <security:intercept-url pattern="/board/insert" access="hasRole('ROLE_MEMBER')" /> <security:intercept-url pattern="/board/update" access="hasRole('ROLE_MEMBER')" /> <!-- <security:access-denied-handler error-page="/accessError" /> error-page 나 ref 둘 중 하나만 !!! --> <security:access-denied-handler ref="customAccessDenied" /> <!-- <security:form-login /> --> <!-- 로그인창으로 강제 이동 시 해당하는 페이지 --> <security:form-login login-page="/customLogin" authentication-success-handler-ref="customLoginSuccess"/> </security:http> <security:authentication-manager> <security:authentication-provider user-service-ref="customUserDetailsService"> <!-- 최종적으로 customUserDetailsService 사용 --> <!--<security:jdbc-user-service data-source-ref="dataSource" users-by-username-query="select userid,userpw,enabled from tbl_member where userid=?" authorities-by-username-query="select userid,auth from tbl_auth where userid=?" /> change to Bcrypt <security:password-encoder ref="customPasswordEncoder" /> --> <security:password-encoder ref="bcryptPasswordEndcoder" /> </security:authentication-provider> <!-- ********************************************************************************************* <security:authentication-provider> <security:user-service> <security:user name="member" password="{noop}member" authorities="ROLE_MEMBER" /> <security:user name="admin" password="{noop}admin" authorities="ROLE_MEMBER, ROLE_ADMIN" /> </security:user-service> </security:authentication-provider> *********************************************************************************************** --> </security:authentication-manager> </beans> --------------------------------------------------------------------------------------
>>> servlet-context.xml
( Namespace의 security 추가 )
( 상단의 시큐리티 버전 5.0 숫자 지우고, global-method 태그 추가 )
<?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" xmlns:security="http://www.springframework.org/schema/security" xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://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 /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.jslhrd.controller" /> <security:global-method-security pre-post-annotations="enabled" secured-annotations="enabled" /> <!-- security 어노테이션을 사용하기 위한 태그 (Namespace의 security 추가 후, 상단의 5.0버전 숫자 제거) --> </beans:beans>


>>> STS 기초 세팅
Window -> Preference -> encoding 검색 -> Workspace,CSS,HTML,JSP,XML (UTF-8 변경)
Window -> Preference -> General -> Startup&Shutdown -> Workspaces (Prompt 체크, workspaces 선택)
Window -> Web Browser -> Chrome or Default
Servers -> Spring 기본 서버 삭제 -> New -> Tomcat v9.0 추가 후 경로 설정
Tomcat -> Overview (HTTP/1.1 -> 8087변경) -> Modules (Path -> / 변경)
main/wepapp/resources -> css,fonts,images,js 폴더 관리
Window -> Preferences -> XML -> XML Catalog -> UserSpecifiedEntries 클릭, Add 클릭,
     Location = http://mybatis.org/dtd/mybatis-3-mapper.dtd
     Key = -//mybatis.org//DTD Mapper 3.0//EN

-----------------------------------------------------------------------------------------------------------------------------

>>> hanulso/pom.xml 기초 세팅
java-version -> 1.8
springframework-version -> 5.0.7.RELEASE (@Get/PostMapping 어노테이션 사용 가능)
log4j-version -> 1.2.17

lombok-1.18.22 추가
HikariCP-2.7.4 추가 (커넥션 풀 처리)
mybatis(3.4.6), mybatis-spring(2.0.7), spring-txt, spring-jdbc 추가 (DB연동 처리)
commons-fileupload-1.3.3, commons-io-2.6 추가 (파일 첨부 처리)
thumbnailator-0.4.8 추가 (썸네일 이미지 생성시)
spring security 추가
jackson-databind-2.9.6 추가 (JOSN 포맷 변환)
jackson-dataformat-xml-2.9.6 추가 (xml 처리)
gson-2.8.2 추가 (테스트시 java instance를 json 타입의 문자열로 변환 처리)
javax.mail-1.6.2 추가 (메일 처리)
spring-context-support 추가 (캐쉬,메일,스케줄링,UI 등 부가적 기능)

junit-version -> 4.12
maven-compiler-plugin -version -> 3.5.1 & 1.8 & 1.8


https://mvnrepository.com/ <- dependency 검색
https://start.spring.io/ <- Spring Start Page

- 세팅이 반이다 !
- Test 중요 !
- build path (mysql-connector-java-8.0.28.jar , ojdbc8.jar)
- pom.xml 계속 수정

STS 세팅

    Window -> Preference -> encoding 검색 -> Workspace,CSS,HTML,JSP,XML (UTF-8 변경)
    Window -> Preference -> General -> Startup&Shutdown -> Workspaces (Prompt 체크, workspaces 선택)
    Window -> Web Browser -> Chrome or Default
    Servers -> Spring 기본 서버 삭제 -> New -> Tomcat v9.0 추가 후 경로 설정
    Tomcat -> Overview (HTTP/1.1 -> 8087변경) -> Modules (Path -> / 변경)
    main/wepapp/resources -> css,fonts,images,js 등의 폴더 관리
    Window -> Preferences -> XML -> XML Catalog -> UserSpecifiedEntries 클릭, Add 클릭,
      Location = http://mybatis.org/dtd/mybatis-3-mapper.dtd
      Key = -//mybatis.org//DTD Mapper 3.0//EN

MVC

   (Model View Controller)

   Presentation - Client의 요청을 받아 Business에게 처리를 전달.
   Business - 실제 요청에 대한 처리를 담당. (Service)
   Persistence - Business의 처리에 따라 데이터베이스에 접근. 저장,조회,삭제 등 수행.

Layered Architecture


   각 계층은 자신의 계층이 갖는 책임에만 충실하도록 개발해야 한다.

View

Model Model

Presentation
@Controller

Model Model

Business
@Service

DTO Model

Persistence

DTO Model

DB
(Oracle)



초기 설정/관리해야 할 .XML

p.608
    - pom.xml : 프로그램 추가(버전관리), spring5.0.7
    - web.xml : 한국어 지원, 로그인 지원
    - root-context.xml : DB 연결 지원
    - servlet-context.xml : spring security 어노테이션 설정 추가
    - security-context.xml : 로그인 관련( 인증 + 권한 )


동기 VS 비동기


    - 동기(Synchronized) : 프로그램이 작성된 순서대로 실행되는 것.
       반드시 앞의 동작이 끝나야 다음의 동작이 실행 됨.
    - 비동기(Asynchronized) : 타임라인의 분기를 나눠서 두개 이상의 함수가 동시에 동작하는 것.
    - Callback 함수 : 비동기로 함수를 실행할 경우라도 A -> B 동작 순서가 구분되어야 하는데,
       이런 경우 B를 callback함수로 A함수의 인자로 호출하면 온전하게 실행 가능.
    - promise : 무수히 중첩되는 복잡한 callback함수의 지옥을 대신하여 사용.
       비동기 작업이 종료된 후, 작업 실행의 성공,실패,결과값의 내용이 무엇인지 반환해주겠다고 약속해주는 객체.


mapper.xml


    전 프로젝트(jslhrd)에서는 src/main/resources 폴더에 mapper.xml 파일을 저장했지만,
    본 프로젝트(hanulso)에서는 mapper.xml 파일을 Mapper인터페이스가 있는 패키지와 같은 곳에 저장.
    xml 파일 dtd 환경설정 방법은 매뉴얼(STS 기초세팅) 참조.
    NoticeVO & DB(NOTICE 테이블) & Mapper.xml 의 각 변수명을 통일함에 주의.


(Oracle) Primary Key


    테이블 생성시 PK를 설정할 때, 컴럼 생성 문구 옆에 PRIMARY KEY를 입력하면,
    인덱스에 원치않는 이름의 pk가 생성되어 버린다.
    고로 컴럼 생성 문구를 다 적은 후, 마지막 줄에 constraint 제약조건 설정으로 PK 생성.
    CONSTRAINT 제약조건명 PRIMARY KEY (컬럼명)
    ex) constraint pk_notice PRIMARY KEY (bno)
    *테이블 생성 후, 따로 설정 가능.
    ex) ALTER TABLE 테이블명 ADD CONSTRAINT 제약조건명 PRIMARY KEY (컬럼명)


core / fmt 태그


    <c:forEach var="notice" items="${notice_list}" varStatus="status">
    status.index -> varStatus를 사용하여 반복문의 각 변수의 "0부터의 순서"를 나타냄.

    <c:set var="cnt" value="${notice_count}" />
    c:set -> core태그를 사용하여 변수명과 값을 지정해 새로운 변수 생성.

    <fmt:formatDate value="${regdate}" pattern="yyyy-MM-dd HH:ss" />
    formatDate -> fmt 태그를 사용하여 해당 변수를 원하는 패턴형식의 날짜로 출력.
    *value의 값이 String타입이면 오류가 발생. java.util.Date or java.sql.Date 타입 사용.


프로젝트 (포트폴리오) 계획


    1. 주제
    2. 개발 목적
    3. ERD맵 (테이블 설계)
    4. 화면 구현
    5. Tree Map (각 화면별 필요한 기능 정리)


Gyoon