1. 관심 주제 도메인
관심 주제 (Tag)는 엔티티인가? 도메인인가?
Tag 독자적인 라이프사이클이 있고 다른 곳(Study)에서도 참조할 것이기때문에 엔티티이다.
@Entity
@Getter @Setter @EqualsAndHashCode(of = "id")
@Builder @AllArgsConstructor @NoArgsConstructor
public class Tag {
@Id @GeneratedValue
private Long id;
@Column(unique = true, nullable = false)
private String title;
}
Tag 엔티티 관계
구현코드
github.com/loosie/spring_jpa_study__dotStudy/commit/13235f8686fc278a0ca075953cebeac248a42e69
2. 관심 주제 등록 뷰
☛ SQL 로깅 확인 설정
application.propeties
# 개발할 때에만 create-drop 또는 update를 사용하고 운영 환경에서는 validate를 사용합니다.
spring.jpa.hibernate.ddl-auto=create-drop
# 개발시 SQL 로깅을 하여 어떤 값으로 어떤 SQL이 실행되는지 확인합니다.
spring.jpa.properties.hibernate.format_sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
사용한 프론트엔트 라이브러리
1. ~resources/static/ 경로에 설치
$ npm inastall @yaireo/tagify
2. fragments.html에 추가
<link rel="stylesheet" href="/node_modules/@yaireo/tagify/dist/tagify.css" />
tags.html에 적용
<script src="node_modules/@yaireo/tagify/dist/tagify.min.js"></script>
<script type="application/javascript">
$(function(){
function tagRequest(url, tagTitle) {
$.ajax({
dataType: "json",
autocomplete: {
enabled: true,
rightKey: true,
},
contentType: "application/json; charset=utf-8",
method: "POST",
url: "/settings/tags" + url,
data: JSON.stringify({'tagTitle': tagTitle})
}).done(function (data, status) {
console.log("${data} and status is ${status}");
});
}
function onAdd(e) {
tagRequest("/add", e.detail.data.value);
}
function onRemove(e) {
tagRequest("/remove", e.detail.data.value);
}
var tagInput = document.querySelector("#tags");
var tagify = new Tagify(tagInput, {
pattern: /^.{0,20}$/,
whitelist: JSON.parse(document.querySelector("#whitelist").textContent),
dropdown : {
enabled: 1, // suggest tags after a single character input
} // map tags
});
tagify.on("add", onAdd);
tagify.on("remove", onRemove);
// add a class to Tagify's input element
tagify.DOM.input.classList.add('form-control');
// re-place Tagify's input element outside of the element (tagify.DOM.scope), just before it
tagify.DOM.scope.parentNode.insertBefore(tagify.DOM.input, tagify.DOM.scope);
});
</script>
뷰 완성
구현코드
github.com/loosie/spring_jpa_study__dotStudy/commit/7b3e535b946bf124abecb3173d14989abf828f46
3. 관심 주제 등록 기능 구현
타임리프 자바스크립트 템플릿으로 Ajax 호출시 CSRF 토큰 설정
<script type="application/javascript" th:inline="javascript"> $(function() { var csrfToken = /*[[${_csrf.token}]]*/ null; var csrfHeader = /*[[${_csrf.headerName}]]*/ null; $(document).ajaxSend(function (e, xhr, options) { xhr.setRequestHeader(csrfHeader, csrfToken); }); }); </script> |
구현코드
github.com/loosie/spring_jpa_study__dotStudy/commit/62e79cd6be77f306b648ceb321aac58edd1be338
4. 관심 주제 조회
thymeleaf #strings
들어온 Tag 데이터 형태 : List<String> tags = List.of("Stirng", Java", ...);
바꿀 데이터 형태 : Spirng, Java, ...
th:value="${#strings.listJoin(tags, ',')}
이미 등록된 태그 불러오기
태그 조회 후 불러오는 쿼리문
구현코드
github.com/loosie/spring_jpa_study__dotStudy/commit/69db1e01f5229787204656b45b4ed47e176faeb0
5. 관심 주제 삭제
태그 삭제
- DB에 없는 태그라면, Bad Request로 응답하고
- DB에 있는 태그라면 Account에서 삭제 (DB에서 태그 정보를 삭제 하는게 아니라 연관 관계만 삭제하는 것임)
구현코드
github.com/loosie/spring_jpa_study__dotStudy/commit/302db4febbd66813ab0c29e7b631c4e807a541d3
6. 관심 주제 자동완성
기존의 태그 정보 자동완성 목록으로 제공하는 기능
- Tagify의 whitelist를 사용한다.
- https://yaireo.github.io/tagify/#section-manual-suggestions
ObjectMapper
- 객체를 JSON으로 JSON을 객체로 변환할 때 사용하는 유틸리티
- https://github.com/FasterXML/jackson
구현코드
github.com/loosie/spring_jpa_study__dotStudy/commit/cc4bb3dad5f739edb691a1ceafd2e64f37302b54
7. 관심 주제 테스트
요청 본문에 JSON 데이터를 실어 보내기
mockMvc.perform(post(SettingsController.SETTINGS_TAGS_URL + "/add") .contentType(MediaType.APPLICATION_JSON) .content(objectMapper.writeValueAsString(tagForm)) .with(csrf())) .andExpect(status().isOk()); |
테스트에 트랜잭션 적용하기
@Transactional @SpringBootTest @AutoConfigureMockMvc class SettingsControllerTest { ... } |
구현코드
github.com/loosie/spring_jpa_study__dotStudy/commit/32c7b27b401127d5b5c8ce5be3055ae47cd53bc6
8. 지역 도메인
지역(zone)도 역시 밸류가 아닌 엔티티!
Zone
- City (영문 도시 이름)
- LocalNameOfCity (한국어 도시 이름)
- Province (주 이름, nullable)
Account와 Zone의 객체 지향적인 관계
- 다대다 (@ManyToMany) 단방향 관계
Account와 Zone의 관계형 관계
- 조인 테이블을 사용한 두개의 1대다 관계
지역 데이터 초기화
- 위키 피디아 데이터 참조
- https://en.wikipedia.org/wiki/List_of_cities_in_South_Korea
- 데이터를 CVS로 옮기고 초기화 하기
구글 스프레드 시트에 복붙 후 csv파일로 다운로드
/resources 폴더에 저장
csv내용 zoneRepository에 저장하기
@PostConstruct
public void initZoneData() throws IOException {
if(zoneRepository.count() ==0){
Resource resource = new ClassPathResource("zones_kr.csv");
List<Zone> zoneList = Files.readAllLines(resource.getFile().toPath(), StandardCharsets.UTF_8).stream()
.map(line -> {
String[] split = line.split(",");
return Zone.builder().city(split[0]).localNameOfCity(split[1]).province(split[2]).build();
}).collect(Collectors.toList());
zoneRepository.saveAll(zoneList);
}
}
구현코드
github.com/loosie/spring_jpa_study__dotStudy/commit/baa554848977afdb9e944c0a6f2a83d3549f705e
9. 지역 정보 추가 삭제 및 텍스트
주요 활동 지역
- 태그 관리와 차이점은 미리 제공하는 데이터에서만 선택할 수 있다는 점
기존의 지역 정보 자동완성 목록에서만 선택 가능하다.
- Tagify의 whitelist를 사용한다.
- https://yaireo.github.io/tagify/#section-textarea
var tagify = new Tagify(tagInput, { enforceWhitelist: true, whitelist: JSON.parse(document.querySelector("#whitelist").textContent), dropdown : { enabled: 1, // suggest tags after a single character input } // map tags }); |
구현코드
github.com/loosie/spring_jpa_study__dotStudy/commit/1bb5d162e9914cac2c3e07a88aea571ea7d7e894
참고
인프런 강의 - 스프링과 JPA 기반 웹 애플리케이션 개발
'Dot Programming > Spring Clone' 카테고리의 다른 글
[스프링 웹앱 프로젝트 #42] PostgreSQL 설치 및 Spring 연동 (0) | 2021.04.28 |
---|---|
[스프링 웹앱 프로젝트 #32] 패스워드를 잊어버렸습니다 (0) | 2021.03.09 |
[스프링 웹앱 프로젝트 #31] 닉네임 수정 (0) | 2021.03.09 |
[스프링 웹앱 프로젝트 #30] ModelMapper적용 (0) | 2021.03.08 |
[스프링 웹앱 프로젝트 #29] 알림 설정 (0) | 2021.03.05 |