Project/ClassFlix

[ClassFlix] EP 5. view 페이지 제작과 컨트롤러 연결 - 1

목차 (클릭시 해당 목차로 이동)


     

     

     

     

    이제는 View 계층 설계 및 구현의 차례이다.

     

     

    index.html 제작

    설계

    • body header와 footer는 모든 곳에서 쓰기 때문에 여기서 미리 제작해놓는다.
    • 점보트론으로 CLASS FLIX를 표시한다.
    • NetFlix의 뷰 아이디어를 따왔다. 홈화면에서 category별 인터넷 강의를 바로 볼 수 있도록 한다.

     

     

     

     

    구현

    header

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head th:fragment="header">
        <title>CLASS FLIX</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <meta name="viewport" content="width=device-width" initial-scale="1">
        <link rel="stylesheet" href="/css/bootstrap.css">
        <link rel="stylesheet" href="/css/classflix.css">
    </head>

     

     

    bodyHeader

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <nav th:fragment="bodyHeader" class="navbar navbar-default">
        <div class="container-fluid">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                        data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                    <span class="sr-only"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand" href="/">CLASS FLIX</a>
            </div>
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav navbar-right">
                    <li><a href="/members/new">회원가입<span class="sr-only"></span></a></li>
                    <li><a href="#">강의등록</a></li>
                </ul>
            </div>
        </div>
    </nav>

     

     

     

    footer

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <footer th:fragment="footer" style="background-color: #000000; color: #ffffff">
        <div class="container">
            <br>
            <div calss="row">
                <div class="col-sm-4" style="text-align: center;"><h5>Copyright &copy; 2021</h5><h5>김동호(Dongho Kim)</h5></div>
                <div class="col-sm-4"><h4>대표자 소개</h4><p>저는 CLASS FLIX의 대표 김동호입니다. 홍익대학교 컴퓨터공학과에 재학중입니다.</p></div>
                <div class="col-sm-4"><h4 style="text-align: center;">SNS</h4>
                    <div class="list-group">
                        <a href="https://www.youtube.com/channel/UCzPBLnZ88905X61WRQy9EpQ" class="list-group-item">유투브</a>
                        <a href="https://www.github.com/dongho108" class="list-group-item">깃허브</a>
                        <a href="https://ksabs.tistory.com/" class="list-group-item">블로그</a>
                    </div>
                </div>
            </div>
        </div>
    </footer>

     

     

    home (index.html)

     

    <!DOCTYPE HTML>
    <html xmlns:th="http://www.thymeleaf.org">
    <head th:replace="fragments/header :: header">
    </head>
    <body>
    <style type="text/css">
        .jumbotron {
            text-shadow: black 0.2em 0.2em 0.2em;
            color: red;
        }
    
        .lecture-images {
            width: 128px;
            height: 83px;
        }
        .panel-heading {
            font-weight: bold;
            background-color: white;
        }
        .lecture-title {
            font-weight: bold;
        }
        .star_rating {font-size:0; letter-spacing:-4px;}
        .star_rating a {
            font-size:22px;
            letter-spacing:0;
            display:inline-block;
            margin-left:5px;
            color:#ccc;
            text-decoration:none;
        }
        .star_rating a:first-child {margin-left:0;}
        .star_rating a.on {color:#E1BC3F;}
    
    </style>
    <div th:replace="fragments/bodyHeader :: bodyHeader" />
    
    <div class="container">
        <div class="jumbotron">
            <h1 class="text-center"> CLASS FLIX</h1>
            <p class="text-center" style="text-shadow: none"> 인강 추천좀 </p>
        </div>
        <div class="row">
            <div class="panel panel-default">
                <div class="panel-heading">IT 분야 인기 강의</div>
                <div class="panel-body">
                    <div class="col-md-3">
                        <img class="lecture-images" src="/images/springInstroduction.png" alt="스프링입문">
                        <h5 class="lecture-title">스프링입문</h5>
                        <p class="star_rating">
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                        </p>
                    </div>
                    <div class="col-md-3">
                        <img class="lecture-images" src="/images/springCore.jpeg" alt="스프링코어">
                        <h5 class="lecture-title" >스프링코어</h5>
                        <p class="star_rating">
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#">★</a>
                        </p>
                    </div>
                    <div class="col-md-3">
                        <img class="lecture-images" src="/images/jpa.png" alt="jpa기초">
                        <h5 class="lecture-title" >JPA기초</h5>
                        <p class="star_rating">
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#">★</a>
                            <a href="#">★</a>
                        </p>
                    </div>
                    <div class="col-md-3">
                        <img class="lecture-images" src="/images/jpaPrac1.png" alt="jpa활용1">
                        <h5 class="lecture-title" >JPA활용1</h5>
                        <p class="star_rating">
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                        </p>
                    </div>
                </div>
            </div>
            <div class="panel panel-default">
                <div class="panel-heading">요리 분야 인기 강의</div>
                <div class="panel-body">
                    <div class="col-md-3">
                        <img class="lecture-images" src="/images/springInstroduction.png" alt="스프링입문">
                        <h5 class="lecture-title">스프링입문</h5>
                        <p class="star_rating">
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                        </p>
                    </div>
                    <div class="col-md-3">
                        <img class="lecture-images" src="/images/springCore.jpeg" alt="스프링코어">
                        <h5 class="lecture-title" >스프링코어</h5>
                        <p class="star_rating">
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#">★</a>
                        </p>
                    </div>
                    <div class="col-md-3">
                        <img class="lecture-images" src="/images/jpa.png" alt="jpa기초">
                        <h5 class="lecture-title" >JPA기초</h5>
                        <p class="star_rating">
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#">★</a>
                            <a href="#">★</a>
                        </p>
                    </div>
                    <div class="col-md-3">
                        <img class="lecture-images" src="/images/jpaPrac1.png" alt="jpa활용1">
                        <h5 class="lecture-title" >JPA활용1</h5>
                        <p class="star_rating">
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                            <a href="#" class="on">★</a>
                        </p>
                    </div>
                </div>
            </div>
        </div>
    </div>
    
    <div th:replace="fragments/footer :: footer" />
    
    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    
    </body>
    </html>

     

     

    결과

     

    * 강의부분은 어떻게 구성되어야할지 미리 테스트 이미지와 데이터를 html 상에서 넣어놓았다.

     

     

     

     

     

     

    MemberForm 제작

    설계

    • Member에 대한 정보 (이름, 나이, 성별, 직업)을 등록할 수 있게한다.
    • 내비게이션의 회원가입을 누르면 연결될 수 있도록 한다.

     

    구현

     

    memberForm

    <!DOCTYPE HTML>
    <html xmlns:th="http://www.thymeleaf.org">
    <head th:replace="fragments/header :: header" />
    <style>
        .fieldError {
            border-color: #bd2130;
        }
    </style>
    <body>
    <div th:replace="fragments/bodyHeader :: bodyHeader"/>
    <div class="container">
        <div class="page-header">
            <h1 class="text-center">회원가입</h1>
        </div>
        <form role="form" action="/members/new" th:object="${memberForm}"
              method="post">
            <div class="form-group">
                <label th:for="name">이름</label>
                <input type="text" th:field="*{name}" class="form-control" placeholder="이름을 입력하세요"
                       th:class="${#fields.hasErrors('name')}? 'form-control fieldError' : 'form-control'">
                <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Incorrect date</p>
            </div>
            <div class="form-group">
                <label th:for="age">나이</label>
                <input type="text" th:field="*{age}" class="form-control"placeholder="나이를 입력하세요">
            </div>
            <div class="form-group">
                <label th:for="gender">성별</label>
                <input type="text" th:field="*{gender}" class="form-control"
                       placeholder="성별을 입력하세요">
            </div>
            <div class="form-group">
                <label th:for="career">직업</label>
                <input type="text" th:field="*{career}" class="form-control"
                       placeholder="직업을 입력하세요">
            </div>
            <div class="text-center">
                <button type="submit" class="btn btn-primary">등록하기</button>
            </div>
    
        </form>
        <br/>
    </div> <!-- /container -->
    <div th:replace="fragments/footer :: footer" />
    </body>
    </html>

     

     

     

    컨트롤러

    설계

    • HomeController 에서 첫 화면 (홈화면)을 연결한다.
    • MemberController에서 memberForm을 연결한다. (정보는 DTO로 전달)
    • memberForm dto에서는 이름을 필수로 적게 @NotEmpty를 건다.

    구현

     

     

    HomeController

    package dongho.classflix.controller;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    @Controller
    public class HomeController {
    
        @RequestMapping("/")
        public String home() {
            return "home";
        }
    }
    

     

    MemberController

    package dongho.classflix.controller;
    
    import dongho.classflix.service.MemberService;
    import lombok.RequiredArgsConstructor;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.GetMapping;
    
    @Controller
    @RequiredArgsConstructor
    public class MemberController {
    
        private final MemberService memberService;
    
        @GetMapping("/members/new")
        public String createForm(Model model) {
            model.addAttribute("memberForm", new MemberForm());
            return "members/memberForm";
        }
    }
    

     

    MemberForm (dto)

    package dongho.classflix.controller;
    
    import dongho.classflix.domain.Gender;
    import lombok.Getter;
    import lombok.Setter;
    
    import javax.validation.constraints.NotEmpty;
    
    @Getter
    @Setter
    public class MemberForm {
    
        @NotEmpty(message = "회원 이름은 필수 입니다")
        private String name;
    
        private int age;
        private Gender gender;
        private String career;
    }
    

     

     

    memberForm.html

    <!DOCTYPE HTML>
    <html xmlns:th="http://www.thymeleaf.org">
    <head th:replace="fragments/header :: header" />
    <style>
        .fieldError {
            border-color: #bd2130;
        }
    </style>
    <body>
    <div th:replace="fragments/bodyHeader :: bodyHeader"/>
    <div class="container">
        <div class="page-header">
            <h1 class="text-center">회원가입</h1>
        </div>
        <form role="form" action="/members/new" th:object="${memberForm}"
              method="post">
            <div class="form-group">
                <label th:for="name">이름</label>
                <input type="text" th:field="*{name}" class="form-control" placeholder="이름을 입력하세요"
                       th:class="${#fields.hasErrors('name')}? 'form-control fieldError' : 'form-control'">
                <p th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Incorrect date</p>
            </div>
            <div class="form-group">
                <label th:for="age">나이</label>
                <input type="text" th:field="*{age}" class="form-control"placeholder="나이를 입력하세요">
            </div>
            <div class="form-group">
                <label th:for="gender">성별</label>
                <input type="text" th:field="*{gender}" class="form-control"
                       placeholder="성별을 입력하세요">
            </div>
            <div class="form-group">
                <label th:for="career">직업</label>
                <input type="text" th:field="*{career}" class="form-control"
                       placeholder="직업을 입력하세요">
            </div>
            <div class="text-center">
                <button type="submit" class="btn btn-primary">등록하기</button>
            </div>
    
        </form>
        <br/>
    </div> <!-- /container -->
    <div th:replace="fragments/footer :: footer" />
    </body>
    </html>