<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: HEEAH IM</title>
    <description>The latest articles on DEV Community by HEEAH IM (@imheeah).</description>
    <link>https://dev.to/imheeah</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1063352%2F305edb80-04d7-41eb-896c-bf4e3fcb1c2f.png</url>
      <title>DEV Community: HEEAH IM</title>
      <link>https://dev.to/imheeah</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/imheeah"/>
    <language>en</language>
    <item>
      <title>Entity State in JPA/ @Transactional</title>
      <dc:creator>HEEAH IM</dc:creator>
      <pubDate>Tue, 11 Apr 2023 22:47:31 +0000</pubDate>
      <link>https://dev.to/imheeah/entity-state-in-jpa-transactional-39nl</link>
      <guid>https://dev.to/imheeah/entity-state-in-jpa-transactional-39nl</guid>
      <description>&lt;h2&gt;
  
  
  JPA 객체의 상태
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Transient&lt;/strong&gt;&lt;br&gt;
객체를 생성하고, 값을 주어도 JPA나 hibernate가 그 객체에 관해 아무것도 모르는 상태. 즉, 데이터베이스와 매핑된 것이 아무것도 없다.&lt;br&gt;
&lt;strong&gt;2. Persistent&lt;/strong&gt;&lt;br&gt;
저장을 하고나서, JPA가 아는 상태(관리하는 상태)가 된다. 그러나 .save()를 했다고 해서, 이 순간 바로 DB에 이 객체에 대한 데이터가 들어가는 것은 아니다. JPA가 persistent 상태로 관리하고 있다가, 후에 데이터를 저장한다.(1차 캐시, Dirty Checking(변경사항 감지), Write Behind(최대한 늦게, 필요한 시점에 DB에 적용) 등의 기능을 제공한다)&lt;br&gt;
&lt;strong&gt;3. Detached&lt;/strong&gt;&lt;br&gt;
JPA가 더이상 관리하지 않는 상태. JPA가 제공해주는 기능들을 사용하고 싶다면, 다시 persistent 상태로 돌아가야한다.&lt;br&gt;
&lt;strong&gt;4. Removed&lt;/strong&gt;&lt;br&gt;
JPA가 관리하는 상태이긴 하지만, 실제 commit이 일어날 때, 삭제가 일어난다.&lt;/p&gt;
&lt;h2&gt;
  
  
  @Transactional
&lt;/h2&gt;

&lt;p&gt;토큰값이 DB 에 저장되지 않아서 확인해보니, 계정 저장 후, 이메일 토큰을 생성.&lt;br&gt;
Detached 상태의 객체였던 것이다.&lt;/p&gt;

&lt;p&gt;[AS-IS]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private Account saveNewAccount(@Valid SignUpForm signUpForm) {
    Account account = Account.builder()
            ....
            .build();
    return accountRepository.save(account);
}

public void processNewAccount(SignUpForm signUpForm) {
    Account newAccount = saveNewAccount(signUpForm);
    newAccount.generateEmailToken();
    sendSignupConfirmEmail(newAccount);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[TO-BE]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private Account saveNewAccount(@Valid SignUpForm signUpForm) {
    Account account = Account.builder()
            ....
            .build();
    return accountRepository.save(account);
}

@Transactional
public void processNewAccount(SignUpForm signUpForm) {
    Account newAccount = saveNewAccount(signUpForm);
    newAccount.generateEmailToken();
    sendSignupConfirmEmail(newAccount);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이 때 @Transactional 를 사용하여 processNewAccount의 객체도 transaction 범위내에 들도록 한다. 그럼 Detached 상태가 아닌 Persistent 상태가 유지가 된다. Persisent 객체의 경우, transaction이 종료될 때 DB에 sync 된다. 따라서, 생성된 토큰 값도 저장된다.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*참고자료&lt;br&gt;
백기선 인프런 강의&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>jpa</category>
      <category>spring</category>
    </item>
    <item>
      <title>Model Binding : WebDataBinder, @InitBinder</title>
      <dc:creator>HEEAH IM</dc:creator>
      <pubDate>Tue, 11 Apr 2023 22:35:19 +0000</pubDate>
      <link>https://dev.to/imheeah/model-binding-webdatabinder-initbinder-2d5e</link>
      <guid>https://dev.to/imheeah/model-binding-webdatabinder-initbinder-2d5e</guid>
      <description>&lt;h2&gt;
  
  
  Model Binding
&lt;/h2&gt;

&lt;p&gt;@ModelAttribute, @RequestParam, @PathVariable 등을 지정된 파라리터를 @Controller 에 추가하면 다음과 같은 작업이 자동으로 진행된다.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. 파라미터 타입의 object를 만든다.&lt;/strong&gt;&lt;br&gt;
@ModelAttribute User user라는 파라미터를 선언했다면 User 타입의 Object를 생성한다. @SessionAttributes에 의해 세션에 저장된 model object가 있다면 그걸 가져온다. &lt;br&gt;
&lt;strong&gt;2. model object의 property에 웹 파라미터를 바인딩해준다.&lt;/strong&gt;&lt;br&gt;
http를 통해 전달되는 파라미터는 기본적으로 문자열로 되어 있다. Spring의 기본 PropertyEditor를 이용해서 http 파라미터 값을 model의 property type에 맞게 전환한다. 실패시, BindingResult 오브젝트 안에 바인딩 오류를 저장하여 예외를 발생시킨다.&lt;br&gt;
(PropertyEditor은 Spring이 제공하는 DataBinder 인터페이스를 통해 사용된다.)&lt;br&gt;
&lt;strong&gt;3. model 값을 검증한다.&lt;/strong&gt;&lt;br&gt;
이전 단계에서 타입에 대한 검증은 끝났으나 그 외의 검증할 내용이 있다면 적절한 validator를 등록해서 검증할 수 있다. &lt;/p&gt;
&lt;h2&gt;
  
  
  WebDataBinder
&lt;/h2&gt;

&lt;p&gt;AnnotationMethodHandlerAdapter는 @ModelAttribute 등처럼 http요청을 파라미터 변수에 바인딩해주는 작업이 필요한 애노테이션을 만나면 먼저 WebDataBinder를 만든다.&lt;br&gt;
WebDataBinder는 여러 기능을 제공하는데 그 중 http요청으로부터 가져온 문자열을 파라미터 타입의 Object로 변환하는 기능이 있다. 이런 변환 작업은 위에서 언급되었던 PropertyEditor를 이용한다. 따라서 개발자가 직접 만든 커스텀된 PropertyEditor를 적용하려면 WebDataBinder에 등록해줘야 한다. 이 때 필요한게 @InitBinder이다.&lt;/p&gt;
&lt;h2&gt;
  
  
  @InitBinder
&lt;/h2&gt;

&lt;p&gt;WebDataBinder를 초기화해주는 어노테이션이다. InitBinder()는 메소드 파라미터를 바인딩하기전에 자동으로 호출된다. 커스텀한 PropertyEditor, Validator 등을 적용되게 해준다. &lt;br&gt;
아래는 validator를 @InitBinder를 통해 적용한 소스이다.&lt;/p&gt;

&lt;p&gt;[AS-IS]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    private final SignUpFormValidator signUpFormValidator;

    @PostMapping("/signup")
    public String signUpSubmit(@Valid SignUpForm signUpForm, Errors errors) {
        if(errors.hasErrors()){
            return "account/signup";
        }
        signUpFormValidator.validate(signUpForm, errors);
        if(errors.hasErrors()){
            return "account/signup";
        }
        ....
        return "account/signupSuccess";
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[TO-BE]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   private final SignUpFormValidator signUpFormValidator; 

    //form 객체 이름은 변수명이 아니라 type의 camel case를 따라간다.(변수명 바뀌어도 적용된다.삽질 NO)
    @InitBinder("signUpForm")
    public void initBinder(WebDataBinder webDataBinder){
        webDataBinder.addValidators(signUpFormValidator);
    }

    @PostMapping("/signup")
    public String signUpSubmit(@Valid SignUpForm signUpForm, Errors errors) {
        if(errors.hasErrors()){
            return "account/signup";
        }
        ....
        return "account/signupSuccess";
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;* 참고자료&lt;br&gt;
토비의 스프링 Vol. 2 스프링의 기술과 선택&lt;br&gt;
백기선 인프런 강의..&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>spring</category>
    </item>
    <item>
      <title>Thymeleaf</title>
      <dc:creator>HEEAH IM</dc:creator>
      <pubDate>Tue, 11 Apr 2023 22:26:43 +0000</pubDate>
      <link>https://dev.to/imheeah/thymeleaf-4pl</link>
      <guid>https://dev.to/imheeah/thymeleaf-4pl</guid>
      <description>&lt;h2&gt;
  
  
  What is Thymeleaf
&lt;/h2&gt;

&lt;p&gt;Thymeleaf는 server-side JAVA 기반의 template engine 이다.&lt;br&gt;
Spring boot 가 권장하는 템플릿 엔진 중 하나이다.(Groovy, Thymeleaf, FreeMarker..) 그동안 사용해왔던 jsp보다 더 간단한 설정과 표준 문법으로 HTML을 작성할 수 있다. Thymeleaf는 웹 표준, 특히 HTML5 에 맞춰 설계되었기에 완전히 검증된 템플릿을 만들 수 있다.&lt;br&gt;
JSP의 경우, tag libraries를 사용하는 경우, HTML 표준 태그가 아니기에 브라우저가 해석할 수 없는 코드가 된다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;form:inputText name="userName" value="${user.name}" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thymeleaf를 이용하여 작성한 경우, 브라우저가 해석할 수 있는 코드가 된다. 문법 역시 깔끔하게 보인다.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;input type="text" name="userName" value="James Carrot" th:value="${user.name}" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;이로 인해 퍼블리셔, 디자인과 개발팀의 격차를 해소하며 커뮤니케이션을 개선할 수 있는 것을 어필한다.(공식 doc에서..)&lt;/p&gt;

&lt;h2&gt;
  
  
  Standard Expression Syntax
&lt;/h2&gt;

&lt;p&gt;[Simple expressions]&lt;br&gt;
Variable Expressions: ${...}&lt;br&gt;
Selection Variable Expressions: *{...}&lt;br&gt;
Message Expressions: #{...}&lt;br&gt;
Link URL Expressions: @{...}&lt;br&gt;
Fragment Expressions: ~{...}&lt;/p&gt;

&lt;p&gt;[Text operations]&lt;br&gt;
String concatenation: +&lt;br&gt;
Literal substitutions: |The name is ${name}|&lt;/p&gt;

&lt;h2&gt;
  
  
  Thymeleaf Doc
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.thymeleaf.org/doc/tutorials/3.1/usingthymeleaf.html"&gt;Tutorial: Using Thymeleaf&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;사용해보니 개발할 때도 Thymeleaf 가 훨씬 편하다. jsp의 경우 view 템플릿 레더링을 Servlet Container가 하기 때문에 결과를 보는데 딜레이가 있다. 반면 Thymeleaf의 경우는 Servlet Container 개입없이 최종 View를 완성하므로, 바로 확인이 수월하다. 테스트 시에도 Servlet Container를 띄울 필요가 없으므로 mockMVC으로도 테스트 코드 작성이 가능하다.&lt;br&gt;
만약 frond-end 개발자가 Thymeleaf없이 view를 랜더링해서 만들고 있다는 경우라면, 이를 고려하여 attribute 도 추가해줘야 한다.. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>spring</category>
    </item>
  </channel>
</rss>
