타임리프 id 값에 관한 고찰

김설영·2022년 6월 18일
0

MyDiscussions

목록 보기
1/4

field로 생성되는 id가 먼저? label의 for에 지정되는 id가 먼저?

  • for에 있는 id 값을 field가 똑같이 만들어주기도 함

  • 근데 label의 for 값이 없는 경우, field로 인해 생성되는 id값은 name + 1 이었다.

뭐가 먼저랄게 없는 것 같다.

th:each 에서의 id값

<div>
    <div>등록 지역</div>
        <div th:each="region : ${regions}" class="form-check form-check-inline">
            <input type="checkbox" th:field="*{regions}" th:value="${region.key}" class="form-check-input"> 
            <label th:for="${#ids.prev('regions')}"
                       th:text="${region.value}" class="form-check-label">서울</label>
        </div>
</div>
  1. fieldname=regions, id=regions1, 2, 3...과 같이 임의의 id를 부여함
  2. label안의 th:for=${#ids.prev('regions')}fieldid값을 참조함

위의 메커니즘으로 checkboxid값과 labelid값이 동일해지는 듯 하다.

하지만, 솔직히 '#ids.prev('regions')라는 녀석의 메커니즘이 너무 이해가 가지 않았다.

얘는 어떻게 field가 생성한 id값을 참조하는거야?

타임리프가 제공하는 ids.prev()코드를 뜯어보자.

public String prev(final Object id) {
        Validate.notNull(id, "ID cannot be null");
        final String str = id.toString();
        return str + this.context.getIdentifierSequences().getPreviousIDSeq(str);
    }

타임리프가 제공하는 Ids라는 class의 prev() 메서드이다.
메서드의 특징은 다음과 같다.

  • 파라미터로 id값을 Object로 받는다.
  • 받은 id값을 toString()을 통해 String타입으로 변환한다.
  • String타입의 id값 뒤에 수상한 것을 붙여준다.

수상한 this.context.getIdentifierSequences().getPreviousIDseq(str);의 정체?

  • ITemplateContext 타입인 context

    • ITemplateContext는 하나의 interface이다.
    • 해당 인터페이스는 template processing과 관련된 context를 포함하는 모든 클래스들이 구현하였다.
    • 해당 인터페이스 중, prev()메서드가 사용하는 메서드는 getIdentifierSequence() 메서드이다.
    • 해당 메서드는 IdentifierSequences를 반환한다
  • getIdentifierSequences()IdentifierSequences를 얻는다.

  • 해당 클래스에는 Map<String, Integer> idCounts 변수와 getPreviousIDseq()이라는 메서드가 있다.

    public Integer getPreviousIDSeq(final String id) {
        Validate.notNull(id, "ID cannot be null");
        final Integer count = this.idCounts.get(id);
        if (count == null) {
            throw new TemplateProcessingException(
                    "Cannot obtain previous ID count for ID \"" + id + "\"");
        }
        return Integer.valueOf(count.intValue() - 1);
    }
  • Map<String, Integer> idCounts

    • id 값마다 카운트 횟수가 Map형태로 저장되는 듯 하다.
    • id 값이란, 위 예제에서의 regions이다.
    • th:each문을 돌 때 마다 id(regions)가 몇 회나 카운트되었는지 기록되는 듯 하다.
    • count는 1부터 시작한다.
  • getPreviousIDseq(String id)

    • 해당 메서드는 String 타입의 id값을 파라미터로 받는다.
    • id값은 가장 마지막에 count된 ID값이다.
    • 메서드 실행 결과로, count를 반환한다.
  • 위 예제에서의 id값의 count

    • count는 1부터 시작하므로 1일 것이다. //count=1
    • regions또한 count=1이므로, th:field="*{regions}id=regions1을 생성하고 count에 1을 추가한다. //count = 2
    • labelth:for=${#ids.prev('regions')}id값을 만들기 위해 메서드를 수행한다.
    • getPreviousIDseq(String id)에 의해 count - 1값이 반환되어 1을 반환한다. //count = 2 였으므로, 해당 메서드에 의해 1이 반환된다.
    • 1id값인 'regions'뒤에 붙여 'regions1'을 반환한다.
  • 위의 메커니즘이라면, (filed로 생성된 id가 'regions1'일 때)

    • id.next()regions2를 반환한다.
    • 결과적으로, checkbox의 id값과 labels의 id값이 달라진다.

고찰 : id.prev()field가 생성한 id를 참조하는게 아닌, count횟수를 참조하여 새로 id를 만드는 것 같다. 서로 같기 때문에 참조같아 보이는 것 같은...

결론 : id.prev()th:field로 생성된 id동일한 id를 반환한다!

profile
블로그 이동하였습니당! -> https://kimsy8979.tistory.com/

0개의 댓글