Loading...

Spring/Blog-V1 / / 2022. 3. 3. 23:36

스프링 19강. 웹 페이지 UI 만들기

반응형

 

블로그 웹 페이지를 만들 것이다.

블로그 프로젝트의 파일 구조는 이러하다.

 

이번 시간에는 회원가입 페이지,

로그인 페이지, 글 목록 페이지 UI 작업을 할 것이다.

 


우선 컨트롤러를 만들어보자.

package site.metacoding.dbproject.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;

@Controller
public class PostController {

    // 글쓰기 페이지 /post/writeForm
    @GetMapping("/post/writeForm")
    public String writeForm() {
        return "post/writeForm";
    }

    // 메인 페이지
    // 글 목록 페이지 /post/list/
    @GetMapping({ "/", "post/list" }) // 두 가지 방법으로 들어올 수 있음
    public String list() {
        return "post/list";
    }

    // 글 상세보기 페이지 /post/{id} (삭제버튼 만들어두면 되니까 삭제페이지 필요 X)
    @GetMapping("/post/{id}")
    public String detail(@PathVariable Integer id) { // int는 null이 없음, 초기값이 0
                                                     // Integer는 초기값이 null
        return "post/" + id;
    }

    // 글 수정 페이지 /post/{id}/updateForm
    @GetMapping("/post/{id}/updateForm")
    public String updateForm(@PathVariable Integer id) {
        return "post/updateForm"; // ViewResolver 도움 받음
    }

    // DELETE 글 삭제 /post/{id} -> 글 목록으로 가기
    @DeleteMapping("/post/{id}")
    public String delete(@PathVariable Integer id) {
        return "redirect:/";
    }

    // UPDATE 글 수정 /post/{id} -> 글 상세보기 페이지 가기
    @PutMapping("/post/{id}")
    public String update(@PathVariable Integer id) {
        return "redirect:/post/" + id;
    }

    // POST 글 쓰기 /post -> 글 목록으로 가기
    @PostMapping("/post")
    public String post() {
        return "redirect:/"; // 다시 컨트롤러의 메서드를 찾아가는 것
    }
}
package site.metacoding.dbproject.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;

@Controller
public class UserController {

    // 회원가입 페이지 (정적) - 인증(로그인) X
    @GetMapping("/joinForm")
    public String joinForm() {
        return "user/joinForm";
    }

    // 회원가입 INSERT - 인증(로그인) X
    @PostMapping("/join")
    public String join() { // 행위, 페이지 아님
        return "redirect:/user/loginForm"; // 로그인페이지 이동해주는 컨트롤러 메서드를 재활용
    }

    // 로그인 페이지 (정적) - 인증(로그인) X
    @GetMapping("/loginForm")
    public String loginForm() {
        return "user/loginForm";
    }

    // 로그인 SELECT * FROM user WHERE username=? AND password=?
    // 원래 SELECT는 무조건 GET요청
    // 근데 로그인만 예외! POST요청
    // 이유 : 주소에 패스워드를 남길 수 없으니까!! 보안을 위해!!
    // 로그인 - 인증(로그인) X
    @PostMapping("/login")
    public String login() {
        return "메인 페이지를 돌려주면 됨"; // PostController 만들고 수정하자
    }

    // 유저 상세 페이지 (동적 -> DB연동 필요) - 인증(로그인) O
    @GetMapping("/user/{id}")
    public String detail(@PathVariable int id) {
        return "user/detail";
    }

    // 유저 수정 페이지 - 인증(로그인) O
    @GetMapping("/user/{id}/updateForm")
    public String updateForm(@PathVariable int id) {
        return "user/updateForm";
    }

    // 유저 수정 - 인증(로그인) O
    @PutMapping("/user/{id}")
    public String update(@PathVariable int id) {
        return "redirect:/user/" + id;
    }

    // 로그아웃 - 인증(로그인) O
    @GetMapping("/logout")
    public String logout() {
        return "메인 페이지를 돌려주면 됨"; // PostController 만들고 수정하자
    }
}

 


글 목록 페이지가 메인 페이지이다.

웹 페이지 디자인을 할 때

누가 만들어놓은 디자인을 그대로 갖다 쓰면 편하다.

 

https://www.w3schools.com/bootstrap5/index.php

 

Bootstrap 5 Tutorial

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

bootstrap은 트위터에서 만든 것이다.

미리 만들어놓은 클래스를 사용하는 것이다.

 

추가 참고 사이트

material css https://materializecss.com/

ant design https://ant.design/

 

아래 두 줄의 링크를 걸어주면 사용이 가능하다.

css 파일을 다운로드하여서 사용하는 게 아니라

링크를 걸어서 사용해주는 것을 CDN이라고 한다.

 

CDN(Content Delivery Network) : 컨텐츠를 효율적으로 전달하기 위해

네트워크에 데이터를 저장하여 제공하는 시스템

 

CDN방식을 사용하면 웹서버의 과부하를 줄일 수 있다.

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>

 

 

아래 사진과 같은 내비게이션 바 클래스를 가져올 것이다.

 

사용하기 위해 Example 아래

Try it Yourself 버튼을 눌러준다.

 

그리고 왼쪽의 코드를 모두 복사한다.

 

list.mustache 파일에

그대로 옮겨주자.

<!DOCTYPE html>
<html lang="en">
<head>
  <title>블로그</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<!-- 네비게이션 시작 -->
<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
  <div class="container-fluid">
    <a class="navbar-brand" href="/">Blog</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#collapsibleNavbar">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="collapsibleNavbar">
      <ul class="navbar-nav">
        <li class="nav-item">
          <a class="nav-link" href="/loginForm">로그인</a>
        </li>  
        <li class="nav-item">
          <a class="nav-link" href="/joinForm">회원가입</a>
        </li>
      </ul>
    </div>
  </div>
</nav>
<!-- 네비게이션 끝 -->
</body>
</html>

이때 모든 mustache 파일의

header부분과 footer부분은 반복되기 때문에

따로 layout 파일을 만들어 재사용해주자.

 

mustache의 부분 템플릿 기능을 이용해

파일을 이어 붙이기가 가능하다.

 

네비게이션 바 역시 웹 페이지에서 반복되므로

header에 넣어준다.

 

header.mustache▼

<!DOCTYPE html>
<html lang="en">
<head>
  <title>블로그</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>
<!-- 네비게이션 시작 -->
<nav class="navbar navbar-expand-sm bg-dark navbar-dark">
  <div class="container-fluid">
    <a class="navbar-brand" href="/">Blog</a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#collapsibleNavbar">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="collapsibleNavbar">
      <ul class="navbar-nav">
        <li class="nav-item">
          <a class="nav-link" href="/loginForm">로그인</a>
        </li>  
        <li class="nav-item">
          <a class="nav-link" href="/joinForm">회원가입</a>
        </li>
      </ul>
    </div>
  </div>
</nav>
<!-- 네비게이션 끝 -->

 

footer.mustache▼

<!--웹 페이지의 footer에는 회사의 정보, 홈페이지 정보가 담겨져있다.-->
<div class="mt-4 p-5 bg-secondary text-white rounded">
    <h1>JJJAE_Oo_ni</h1>
    <p>https://jaewon2336.tistory.com/</p>
</div>

</body>
</html>

 

 

https://bibi6666667.tistory.com/269

 

 

[템플릿 엔진] mustache 기본 문법

mustache 기본 문법 정리하기 복잡하지 않으므로 공부 및 연습해 본다! 공식페이지..를 번역한 블로그를 보고 공부했습니다. 1. 변수 {{ , }} 사이에 변수명을 입력한다. 문자열은 자동 HTML 이스케이

bibi6666667.tistory.com

 

부분 템플릿을 사용하여 파일을 이어 붙여주자.

 

{{> /layout/header}}

 

사용하려는 list 파일 기준

layout폴더는 상위에 있기 때문에

/ 를 붙여준다.

 

{{> /layout/header}}

<!-- list.mustache -->

{{> /layout/footer}}

 


 

메인 페이지에 글 목록 css도 가져와보자.

 

Try it Yourself에 다시 들어갈 필요 없이

Example의 코드만 복사해온다.

 

링크를 한 번만 걸어놓으면

다른 클래스를 또 사용할 때 전체 코드를

복사해올 필요는 없다.

 

메인 페이지에 한 번에 보이는 글 개수를 관리하기 위해

페이징 기법을 사용하는데

처음 위치가 왼쪽에 붙어있다.

 

이때 얘들을 가운데로 옮기기 위해서는

flex를 사용하는 게 최고!!

 

얘들을 가운데로 오게 flex를 걸어주려면

부모 태그가 필요하다.

 

근데 이미 ul 태그로 감싸져있네?

검사해서 확인해보니까 ul에 이미 flex가 걸려있다!

 

그럼 방향을 센터로 설정만 해주면 되겠다!

justify-content-center

<!-- ../는 상위폴더로 올라가는 것 -->
{{> /layout/header}}

<!-- 컨테이너 시작 -->
<div class="container mt-3"> <!-- container, mt-3은 css 클래스임!! -->

    <!-- 게시글 아이템 시작 -->
    <div class="card mb-3">
        <div class="card-body">
          <h4 class="card-title">제목입니다.</h4>
          <a href="/post/1" class="btn btn-dark">상세보기</a> <!--나중에 동적으로 id 바꿔줘야함!!!-->
        </div>
    </div>
    <!-- 게시글 아이템 끝 -->

    <!-- 페이지 시작 -->
    <ul class="pagination justify-content-center">
        <li class="page-item disabled"><a class="page-link" href="#">이전</a></li>
        <li class="page-item"><a class="page-link" href="#">다음</a></li>
    </ul>
    <!-- 페이지 시작 -->

</div>
<!-- 컨테이너 끝 -->

{{> /layout/footer}}

 

 

 


 

똑같은 방법으로 필요한 css를 찾아

로그인 페이지와 회원가입 페이지를 만들어주자.

 

joinForm.mustache ▼

{{> /layout/header}}

<!-- 컨테이너 시작 -->
<div class="container mt-3"> <!-- container, mt-3은 css 클래스임!! -->

    <!-- 회원가입 폼 시작 -->
    <form action="/join" method="post">
        <div class="mb-3 mt-3">
          <input type="text" class="form-control" placeholder="Enter username" name="username">
        </div>
        <div class="mb-3">
          <input type="password" class="form-control" placeholder="Enter password" name="password">
        </div>
        <div class="mb-3">
          <input type="email" class="form-control" placeholder="Enter emails" name="email">
        </div>

        <button type="submit" class="btn btn-dark">회원가입</button>
    </form>
    <!-- 회원가입 폼 끝 -->
    
</div>
<!-- 컨테이너 끝 -->

{{> /layout/footer}}

 

loginForm.mustache ▼

{{> /layout/header}}

<!-- 컨테이너 시작 -->
<div class="container mt-3"> <!-- container, mt-3은 css 클래스임!! -->

    <!-- 로그인 폼 시작 -->
    <form action="/login" method="post">
        <div class="mb-3 mt-3">
          <input type="text" class="form-control" placeholder="Enter username" name="username">
        </div>
        <div class="mb-3">
          <input type="password" class="form-control" placeholder="Enter password" name="password">
        </div>
        <!-- 쿠키 - 세션 -->
        <div class="form-check mb-3">
          <label class="form-check-label">
            <input class="form-check-input" type="checkbox" name="remember"> Remember me
          </label>
        </div>
        <button type="submit" class="btn btn-dark">로그인</button>
    </form>
    <!-- 로그인 폼 끝 -->
    
</div>
<!-- 컨테이너 끝 -->

{{> /layout/footer}}

 

remember키는 체크하면 쿼리 스트링에 on으로 날아가고

체크하지 않으면 아무 값도 날아가지 않는다.

 

 

 

 

[출처]

https://cafe.naver.com/metacoding

 

메타코딩 : 네이버 카페

코린이들의 궁금증

cafe.naver.com


메타 코딩 유튜브
https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9

 

메타코딩

문의사항 : getinthere@naver.com 인스타그램 : https://www.instagram.com/meta4pm 깃헙 : https://github.com/codingspecialist 유료강좌 : https://www.easyupclass.com

www.youtube.com

 

반응형