[Spring] 3주차 - Mustache로 화면 구성

12974 단어 SpringSpring

스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - 04장

템플릿 엔진

지정된 템플릿 양식 + 데이터를 합쳐 HTML 문서를 출력하는 소프트웨어
웹 사이트의 화면을 어떤 형태로 만들지 도와주는 양식

  • 서버 템플릿 엔진: JSP, Freemaker 등
    • 서버에서 Java 코드로 문자열을 만든 뒤 HTML로 변환하여 브라우저로 전달
  • 클라이언트 템플릿 엔진: React, Vue 등
    • 이를 이용한 SPA(Single Page Application)는 브라우저에서 화면 생성
    • 서버에서는 json 또는 xml 형식의 데이터만 전달 -> 클라이언트에서 조립
    • 스프링 부트를 사용하면서 자바스크립트를 서버 사이드에서 렌더링하도록 구현하는 것은 쉽지 않음

머스테치(Mustache)

  • 자바스크립트, 파이썬, php 등 다양한 언어를 지원하는 가장 심플한 템플릿 엔진
  • JSP와 같이 HTML 템플릿을 만들어주는 템플릿 엔진
  • 자바에서 사용될 때는 서버, 자바스크립트에서 사용될 때는 클라이언트 템플릿 엔진으로 모두 사용 가능
  • 자바에서 사용되는 서버 템플릿 엔진 (JSP, Velocity, Freemaker, Thymeleaf 등) 대비 장점
    • 간단한 문법
    • 로직 코드 사용 X -> View와 서버의 역할 명확히 분리
    • 하나의 문법으로 클라이언트/서버 템플릿 모두 사용 가능
    • 인텔리제이 커뮤니티 버전으로도 플러그인 사용 가능

파일 위치: src/main/resources/templates

index.mustache 생성

역할: 첫 페이지
간단하게 html 문서 작성

web/IndexController 클래스 생성

역할: 머스테치에 URL 매핑하는 작업

  • 머스테치 스타터의 역할: Controller에서 문자열을 반환할 때 앞의 경로(/src/main/resources/templates)와 뒤의 파일 확장자(.mustache)를 자동 지정
@GetMapping("/")
    public String index() {
        return "index";
    }

/src/main/resources/templates/index.mustache로 전환되어 View Resolver(URL 요청의 결과를 전달할 타입과 값을 지정하는 관리자)가 처리

테스트


게시글 등록 화면 구현

지난 주에 PostsApiController로 API 구현하였음

  • 부트스트랩, jQuery(프론트엔드 라이브러리) 활용: 외부 CDN 활용
    • 레이아웃 방식(공통 영역을 별도 파일로 분리하여 필요한 곳에 가져다 쓰는 방식)으로 추가
    • css는 header에, JavaScript는 footer에 배치하여 페이지 로딩 속도 향상
    • 부트스트랩이 제이쿼리에 의존하는 관계 (제이쿼리가 있어야 부트스트랩 실행)
{{>layout/header}}
    <h1>스프링 부트로 시작하는 웹 서비스</h1>
    <div class="col-md-12">
        <div class="row">
            <div class="col-md-6">
                <a href="/posts/save" role="button" class="btn btn-primary">글 등록</a>
            </div>
        </div>
    </div>
{{>layout/footer}}
  • 글 등록 버튼을 누르면 "/posts/save"로 이동 (아직 API 호출하는 자바스크립트 코드 넣지 않은 상태)

IndexController 클래스에 추가

...
@GetMapping("/posts/save")
    public String postsSave() {
        return "posts-save";
    }
...

posts-save.mustache 생성 및 서버 실행

게시글 등록하는 API 추가

✔ src/main/resources/static에 위치한 정적 파일(자바스크립트, CSS, 이미지 등)은 URL에서 /(절대 경로)로 설정됨


데이터베이스에 정상적으로 저장된다.

전체 조회 기능 구현

  1. index.mustache에 머스테치 문법 사용
    • {{#posts}}: posts라는 List 순회
    • {{변수명}}: List에서 뽑아낸 객체의 필드 사용
  2. PostsRepository 인터페이스에 쿼리 추가
public interface PostsRepository extends JpaRepository<Posts, Long> {
    @Query("SELECT p FROM Posts p ORDER BY p.id DESC")
    List<Posts> findAllDesc();
}
  1. PostsListResponseDto 클래스 생성
  2. PostsService 클래스에 코드 추가
    • postsRopository 결과로 넘어온 Posts의 Stream을 map을 통해 PostsListResponseDto 변환 -> List로 반환
@RequiredArgsConstructor
@Service
public class PostsService {
    private final PostsRepository postsRepository;
    ...
    @Transactional(readOnly = true)
    public List<PostsListResponseDto> findallDesc() {
        return postsRepository.findAllDesc().stream()
        	.map(PostsListResponseDto::new)
        	.collect(Collectors.toList());
    }
}
  1. IndexController 클래스 수정
    • Model: 서버 템플릿 엔진에서 사용할 수 있는 객체를 저장
    • postsService.findAllDesc()로 가져온 결과를 posts로 index.mustache에 전달
private final PostsService postsService;

@GetMapping("/")
public String index(Model model) { // 서버 템플릿 엔진에서 사용할 수 있는 객체를 저장
    model.addAttribute("posts", postsService.findAllDesc());
    return "index";
}

좋은 웹페이지 즐겨찾기