ECC/스프링 부트

[스프링부트] 2. MVC 패턴 이해와 실습

jiheechoi 2025. 5. 23. 02:35

1. 뷰 템플릿과 MVC 패턴

1) 뷰 템플릿이란

-뷰 템플릿은 화면을 담당하는 기술로, 웹 페이지를 하나의 틀로 만들고 여기에 변수를 삽입해 서로 다른 페이지로 보여줌. 

-1장에서 스프링 부트 프로젝트를 만들 때 추가한 머스테치가 바로 뷰 템플릿을 만드는 도구에 해당.

 

2) MVC 패턴

-MVC 패턴: 웹페이지를 화면에 보여주고(view), 클라이언트의 요청을 받아 처리하고(controller), 데이터를 관리하는(model) 역할을 나누는 기법

-컨트롤러: 클라이언트의 요청에 따라 서버에서 이를 처리하는 역할을 함.

-모델: 데이터를 관리하는 역할을 함.

 

2. MVC 패턴을 활용해 뷰 템플릿 페이지 만들기

(1) 뷰 템플릿 페이지 만들기: src > main > resources > templates 에 greetings.mustache 작성

 

(2) 컨트롤러 만들고 실행하기

-컨트롤러는 src > main > java 디렉터리에 있는 기본 패키지 아래에 하나의 패키지로 만듦.

-만든 controller 패키지 밑에 FirstController 클래스를 만들고 이 클래스가 컨트롤러임을 선언하는 @Controller 어노테이션을 작성함.

-반환형이 문자열인 niceToMeetYou() 메서드를 선언하여 앞에서 만든 greetings.mustache 페이지를 반환하도록 함.

-niceToMeetYou 메서드 앞에 @GetMapping()을 추가하고 괄호 안에 URL 주소인 "/hi"를 넣음 -> 페이지(greetings.mustache)를 반환해 달라는 URL 요청을 접수하는 부분임. 웹 브라우저에서 localhost:8080/hi로 접속하면 greetings.mustache 파일을 찾아 반환하라는 뜻.

localhost:8080/hi

 

(3) 모델 추가하기

greetings.mustache에 변수 추가
컨트롤러의 메서드에서 매개변수로 모델을 받아도록 수정하고 username 변수 등록

3. MVC의 역할과 실행 흐름 이해하기

-웹 서비스는 클라이언트-서버 구조로 동작하고, 스프링 부트는 서버의 역할을 함.

-서버는 모델, 뷰, 컨트롤러가 유기적으로 역할을 분담해 클라이언트의 요청을 처리함. -> 컨트롤러가 클라이언트의 요청을 받고, 뷰가 최종 페이지를 만들고, 모델이 최종 페이지에 쓰일 데이터를 뷰에 전달함.

 

1) /hi 페이지의 실행 흐름(FirstController.java)

  1. 이 파일이 컨트롤러임을 선언함.
  2. 클라이언트로부터 "/hi"라는 요청을 받아 접수
  3. "/hi"라는 요청을 받음과 동시에 niceToMeetYou() 메서드를 수행함.
  4. 뷰 템플릿 페이지에서 사용할 변수를 등록하기 위해 모델 객체를 매개변수로 가져옴.
  5. 모델에서 사용할 변수를 등록함. 변숫값에 따라 서로 다른 뷰 템플릿 페이지 출력됨.
  6. 메서드를 수행한 결과로 greetings.mustache 파일 반환함. return 문에는 파일 이름만 작성하면 됨. 

2) /bye 페이지의 실행 흐름

bye.mustache
FirstController 수정

4. 뷰 템플릿 페이지에 레이아웃 적용하기

-레이아웃이란 화면에 요소를 배치하는 일을 말함.

-헤더-푸터 레이아웃은 가장 기본이 되는 레이아웃임. 

  • 상단의 헤더 영역에는 사이트 안내를 위한 내비게이션을 넣음.
  • 하단의 푸터 영역에는 사이트 정보를 넣음.
  • 두 영역 사이에는 사용자가 볼 핵심 내용인 콘텐트를 배치함.

1) /hi 페이지에 헤더-푸터 레이아웃 적용하기

*greetings.mustache 페이지를 쉽고 빠르게 꾸미기 위해 부트스트랩을 사용하자.(부트스트랩이란 웹 페이지를 쉽게 만들 수 있도록 작성해 놓은 코드 모음으로 각종 레이아웃, 버튼, 입력창 등 디자인을 미리 구현해 놓은 것) 

-greetings.mustache 코드 작성

<!doctype html>
<html lang="en">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

    <title>Hello, world!</title>
</head>
<body>
    <!-- navigation -->
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
        <div class="container-fluid">
            <a class="navbar-brand" href="#">Navbar</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                <ul class="navbar-nav me-auto mb-2 mb-lg-0">
                    <li class="nav-item">
                        <a class="nav-link active" aria-current="page" href="#">Home</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="#">Link</a>
                    </li>
                    <li class="nav-item dropdown">
                        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
                            Dropdown
                        </a>
                        <ul class="dropdown-menu" aria-labelledby="navbarDropdown">
                            <li><a class="dropdown-item" href="#">Action</a></li>
                            <li><a class="dropdown-item" href="#">Another action</a></li>
                            <li><hr class="dropdown-divider"></li>
                            <li><a class="dropdown-item" href="#">Something else here</a></li>
                        </ul>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link disabled" href="#" tabindex="-1" aria-disabled="true">Disabled</a>
                    </li>
                </ul>
                <form class="d-flex">
                    <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
                    <button class="btn btn-outline-success" type="submit">Search</button>
                </form>
            </div>
        </div>
    </nav>

    <!-- content -->
    <div class="bg-dark text-white p-5">
        <h1>{{username}}님, 반갑습니다!</h1>
    </div>

    <!-- site info -->
    <div class="mb-5 container-fluid">
        <hr>
        <p> CloudStudying : <a href="#">Privacy</a> : <a href="#">Terms</a></p>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

</body>
</html>

/hi 페이지에 헤더-푸터 레이아웃 적용

 

2) /bye 페이지에 헤더-푸터 레이아웃 적용하기

-앞선 방식과 똑같이 수행한다면 코드가 너무 길고 비효율적이므로 /hi 페이지를 템플릿화해서 사용함. -> 템플릿화란, 코드를 하나의 틀로 만들어 변수화한다는 뜻임.

-특정 코드 영역을 변수화해 사용하려면 각 영역을 발췌하여 템플릿 파일로 만들어야 함(templates 디렉터리)

  • 뷰 템플릿 파일을 불러올 떄는 일반 변수를 {{변수명}}으로 사용하는 것과 달리 {{>파일명}}으로 작성함.greetins.mustache 파일의 내비게이션 바 부분을 잘라내 templates > layouts 디렉터리에 header.mustache로 만들고, 푸터 부분 역시 잘라내 footer.mustache에 붙여넣음.

greetings.mustache 수정
goodbye.mustache 수정

'ECC > 스프링 부트' 카테고리의 다른 글

[스프링 부트] 9장~11장  (0) 2025.06.28
[스프링부트] 1. 스프링 부트 개요  (0) 2025.05.23