Hansel

스프링부트 기초 / 웹 계층 개발 본문

Spring/기초

스프링부트 기초 / 웹 계층 개발

핑슬 2022. 2. 21. 18:00

 

Thymeleaf 의 include 방식

https://www.thymeleaf.org/doc/articles/layouts.html

 

Thymeleaf Page Layouts - Thymeleaf

Summary In this article, we described many ways of achieving the same: layouts. You can build layouts using Thymeleaf Standard Layout System that is based on include-style approach. You also have powerful Layout Dialect, that uses decorator pattern for wor

www.thymeleaf.org

각 태그마다 th:replace는 타임리프상에서 현재 이 태그를 가르키는 경로의 파일로 대체하는 것을 의미한다.

타임리프엔 인클루드 방식과 계층형 방식이 존재한다.

사진은 include 방식으로 완성된 html 파일을 include 하고 싶은 위치에 적용하는 방식이다.

계층형은 배우지 않아 모르지만 배우면 더 편하다고 하니 나중에 배워야 겠다.

 

스프링 Controller

https://goddaehee.tistory.com/203

 

[스프링부트 (2)] SpringMVC(1) Controller 생성하기

[스프링부트 (2)] SpringMVC(1) Controller 생성하기 안녕하세요. 갓대희 입니다. 이번 포스팅은 [ 스프링 부트 Controller  ] 입니다. : ) 아주 간단히 Controller에 대해 정리도 하려고 하니, 실제 스프링..

goddaehee.tistory.com

컨트롤러는 사용자의 요청에 맞게 필요한 작업을 수행한다.

모델 반환하거나 서비스 계층에 위임하는 등의 작업을 한다.

 

장고의 views.py 에 작성하는 함수들과 비슷하며 주소를 매핑해주고 return하는 방식까지 유사하다.
return은 해당 페이지를 리턴하여 화면에 반환하는 것이고 mapping은 url을 매핑하는 것이다.

 

Form 생성

Post 요청으로 보내는 대표적인 작업 중 하나가 이다.

폼을 작성한 뒤 해당 폼을 받아와 데이터가 적절한지 검사하고 저장하는 방식이 많은데 여기서도 비슷하다.

@Controller
@RequiredArgsConstructor
public class MemberController {

    private final MemberService memberService;

    @GetMapping("/members/new") //폼을 가져와 화면에 보내는 역할
    public String createForm(Model model){ //모델을 생성하여 반환 == 폼을 생성하여 반환
        model.addAttribute("memberForm",new MemberForm());
        //장고에서 해당 폼 객체를 생성하여 반환하는 것과 유사함.
        return "members/createMemberForm";
    }

 

우선 사용자를 위한 폼을 받아오는 메서드이다.

model.addAttribute를 통해 (key,value) 쌍으로 모델을 담아 return 문에 작성된 페이지로 보낸다.

위 메서드에선  (memberForm, new MemberForm()) 과 같이 보낸다고 생각하면 된다.

  <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="city">도시</label>
            <input type="text" th:field="*{city}" class="form-control"
                   placeholder="도시를 입력하세요">
        </div>
        <div class="form-group">
            <label th:for="street">거리</label>
            <input type="text" th:field="*{street}" class="form-control"
                   placeholder="거리를 입력하세요">
        </div>
        <div class="form-group">
            <label th:for="zipcode">우편번호</label>
            <input type="text" th:field="*{zipcode}" class="form-control"
                   placeholder="우편번호를 입력하세요">
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>

타임 리프 관련

  • th:object="${}" : 해당 오브젝트를 가져와 사용한다. 컨트롤러에서 해당 오브젝트(폼)을 반환해줬다.
  • th:field="*{}"  : 가져온 오브젝트에서 해당 필드에 입력한다.

그렇게 받아온 폼에 데이터를 입력하고 submit을 하면 Post 요청으로 새로운 동작을 요구한다.

 

Post
  @PostMapping("/members/new") //submit 된 폼을 받아옴
    public String create(@Valid MemberForm memberForm, BindingResult result){

        //오류가 result 에 담긴다
        if(result.hasErrors()){
            return "members/createMemberForm"; //에러가 있으면 다시 작성하는 폼으로 돌아가겠다.
            //현재 매개변수인 memberForm도 같이 가지고 돌아간다
        }

        Address address = new Address(
                memberForm.getCity(), memberForm.getStreet(), memberForm.getZipcode());
        Member member = new Member();
        
        member.setName(memberForm.getName());
        member.setAddress(address);
        
        memberService.join(member); //저장

        return "redirect:/";
    }

폼을 submit 했으니 post 방식의 동작이 필요하다.

작성된 폼을 받아 폼 내용에 문제가 없으면 저장하는 create 메서드 이다

 

폼이 가진 필드의 정보를 가져와 member와 address를 만들어주고 이전에 작성한 memberService를 사용해 db에 저장하도록 데이터를 날려준다.

 

에러 바인딩

만약 특정 필드가 notNull 과 같이 필수 입력인 경우 에러를 나타내야한다.

bindingResult는 에러가 있을 시 그 에러를 해당 객체에 담으며 그에 맞게 코드를 작성해 예외처리를 해주면 된다.

  //오류가 result 에 담긴다
        if(result.hasErrors()){
            return "members/createMemberForm"; //에러가 있으면 다시 작성하는 폼으로 돌아가겠다.
            //현재 매개변수인 memberForm도 같이 가지고 돌아간다
        }

 

목록 조회

타임리프에서 for-each문을 사용해 각 데이터를 태그에 담아 반환한다.

 

            <tr th:each="member : ${members}">
                <td th:text="${member.id}"></td>
                <td th:text="${member.name}"></td>
                <td th:text="${member.address?.city}"></td>
                <td th:text="${member.address?.street}"></td>
                <td th:text="${member.address?.zipcode}"></td>
            </tr>

여기서 '?' 는 null일 경우 표시를 하지 않겠다는 의미이다.