만족은 하되 안주하지는 말자

기록해야 기억한다

프로그래밍/backend&devOps

[SpringBoot] Mustache 에서 Key값이 Null or empty인 경우 처리하기

D36choi 2020. 9. 17. 00:19
728x90

 

package com.hanium.hfrecruit.domain.user;

import com.hanium.hfrecruit.domain.spec.PersonalSpec;
import lombok.*;

import javax.persistence.*;
import java.util.List;

@Data
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ToString(exclude = "personalSpecs")
@Entity
@Table(name = "user")
public class User {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    private Long userNo;

    @Column(nullable = true)
    private String userId;

    @Column(nullable = true)
    private String userPw;

    @Column(nullable = false)
    private String username;

    @Column(nullable = false)
    private String email;

    @Column(nullable = true)
    private String address;

    @Column(nullable = true)
    private String college;

    @Column(nullable = true)
    private String highschool;

    @Column(nullable = true)
    private String birth;

    @Column(nullable = true)
    private Integer gender;

    @Column(nullable = true)
    private String militaryService;

    @Column(nullable = true)
    private String educationLevel;

    @Enumerated(EnumType.STRING) // (1)
    @Column(nullable = false)
    private Role role;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user")
    private List<PersonalSpec> personalSpecs;

    @Builder
    public User(String name, String email, Role role) {
        this.username = name;
        this.email = email;
        this.role = role;
    }

    public void update(String username, String birth, String address, String college, String highschool, String educationLevel, String militaryService, Integer gender){
        this.username = username;
        this.birth = birth;
        this.address = address;
        this.college = college;
        this.highschool = highschool;
        this.educationLevel = educationLevel;
        this.militaryService = militaryService;
        this.gender = gender;
    }

    public String getRoleKey(){
        return this.role.getKey();
    }

}

 이런 형태의, 사용자 프로필을 저장하는 Entity Class 를 만들었다.

 

문제는 controller 에서 Model 에 Attribute 를 추가할 때 발생했다.

 

@ApiOperation(value = "지원서 작성")
    @GetMapping("/apply/{recruitNo}")
    public String apply(@PathVariable Long recruitNo, Model model,
                        @SessionAttribute("user") SessionUser sessionUser){
        User user = userRepository.findByEmail(sessionUser.getEmail()).orElseThrow(
                () -> new IllegalArgumentException("finding userNo Failed!")
        );
        Recruit recruit = recruitRepository.findByRecruitNo(recruitNo)
                .orElseThrow(() -> new NoResultException("error"));
        model.addAttribute("recruit", recruit);
        model.addAttribute("mySpecs",personalSpecService.findAllSpecByUserNo(user.getUserNo()));
        model.addAttribute("pageTitle", "지원서 작성하기");
        model.addAttribute("userProfile",user);
        return "apply";
    }

session 을 통해 사용자email 을 가져오고, 그걸로 user 를 식별해 객체를 주입했다.

 

하지만 address 는 null 허용이 되는 column 이기에 아래와같은 머스태치 문법으로는 문제가 발생한다.

There was an unexpected error (type=Internal Server Error, status=500).

No method or field with name 'userProfile.address' on line 40

com.samskivert.mustache.MustacheException$Context: No method or field with name 'userProfile.address' on line 40

예시로 mustache 문법을 통해 {{userProfile.email}} 을 가져오고자 할때, entity 의 email field 가 Null 이면 model엔 담기지 않는다.

<div class="cols-4">
  <h6>이메일</h6>
  <h4>{{userProfile.email}}</h4>
</div>

 

 

이럴 때는 어떻게 해야할까?

 

머스태치의 "Inverted Section" 을 활용한다.

<div class="cols-4">
  <h6>주소</h6>
  <h4>{{#userProfile.address}}{{userProfile.address}}{{/userProfile.address}}
  {{^userProfile.address}}입력하지 않음{{/userProfile.address}}
  </h4>
</div>

이렇게 하면, key인 address의 value 가 empty,null 인 경우에는 "입력하지 않음"이, 있다면 그 key:value 값을 출력하게 된다.

While sections can be used to render text one or more times based on the value of the key, inverted sections may render text once based on the inverse value of the key. That is, they will be rendered if the key doesn't exist, is false, or is an empty list.

 

내가 이해하기로는, hat('^') 기호는 not 기호와 같은 의미이고, {{#...}}{{/...}} 에 연달아 쓰일 경우에는 그 key의 not 연산을 한 결과가 True 이면 실행된다는 의미다.

 

즉 python 으로 따지자면, list 가 empty 일때, 조건문을 if not list: 라고 해야 해당 조건문이 실행되는 것과 같은 듯 하다.