안녕하세요, Brad입니다. 어제 DB적용과 피드백 적용까지 모두 마쳤네요. 주말에 걸쳐 차근차근 정리해볼게요.
HTML 중복 제거
이전 글에서 HTML 중복 제거하는 방법에 대해 소개했었는데요. 근데 그 부분은 좀 더 오래전에 사용되었던 방법이라고 하네요. 그래서 지난번에서 좀 더 나아간 방법의 HTML 중복 제거를 소개할께요. 우선 base.html을 아래와 같이 만들어놓습니다. base.html은 '틀'이라고 생각하면 될 것 같아요. 그리고 그 안에 우리가 원하는 내용들을 집어넣는 것이죠.
<!DOCTYPE html>
<html lang="kr">
{{> common/header}}
<body>
{{> common/nav}}
{{#block "content"}}
{{/block}}
</body>
</html>
{{> common/footer}}
여기서 {{#block "content"}} {{/block}}
가 동적으로 바뀔 부분이면서 새로 소개할 내용입니다. 물론 {{> common/header}}
, {{> common/nav}}
, {{> common/footer}}
은 모두 반복되는 내용이기 때문에 다른 html파일로 만들어 담아두었구요(지난번 방법에선 이 문법만 사용되었죠?). 그리고 동적으로 바뀔 부분, 즉 "content" 부분은 이것을 사용할 html파일에서 다음과 같이 구성하면 됩니다.
base.html틀을 사용하는 다른 html에서 {{#partial "content"}}{{/partial}}
안에 다르게 변경되어야할 부분을 정의해둡니다. 그렇게 하고 {{> common/base}}
을 이용해 base.html을 부르면 틀 안에 모두 채워지는 것이죠.
DB적용에 맞춰 기능 구현
DB를 적용하게 되면서 기존 Collection에 데이터 담는 부분(List<Question>
또는 List<User>
)이 필요없게 되었습니다(DB에서 가져올 수 있기 때문). 따라서 기존 DB 데이터를 어떻게 가져와야 하는지 알아야할 필요가 생겼습니다!
DB객체를 어떻게 선언할까?
@Autowired private UserRepository userRepository;
- DB객체는 다음과 같이 선언되어 있는데요. 저
userRepository
에 데이터를 넣고 가져올 수 있습니다. 그래서 보통 변수명을 (객체명 + Repository 또는 Dao)로 짓는다고 하네요. - 그럼 저
UserRepository
는 어떻게 선언되어 있을까요? 아래와 같이 '인터페이스'이며CrudRepository<>
을 상속받고 있습니다. 여기서 주의있게 봐야할 부분이<>
안 부분입니다. User는 DB에 넣을 객체를 의미하고,Long
은 PK의 자료형을 의미합니다.User
의 PK로id
를 만들어놓았는데 그게Long
타입이거든요!
public interface UserRepository extends CrudRepository<User, Long> { }
UserRepository
객체를 생성하여 만들어 놓은 곳이 Controller쪽이고 그 안에서 모든 처리를 했다고 생각해봅시다. 그런데 다른 Class에서 이UserRepository
객체가 필요하다면 어떻게 할까요? 답은 그 클래스에서 위에서 한 것과 같이 어노테이션과 함께 해당 객체를 만들어 사용하면 됩니다. 그런데 그 안에 처리된 데이터가 담겨있냐고요? 네!! DB에서 가져오는 것이기 때문에 다른 클래스에서 다른 객체로 처리하였다고 하더라도 상관없습니다!!
- DB객체는 다음과 같이 선언되어 있는데요. 저
DB안의 값을 가져오려면?
- 이번 미션에서 사용한 메서드는 딱 2개였습니다.
findAll()
와findById()
입니다.findAll()
은 DB안 해당 테이블의 모든 값들을 가져오는데요.Iterable
타입으로 반환합니다. Model 안에 바로 넣어 값을 넘겨줄 수 있더라구요. - 반면
findById()
는 매개변수 안에 PK를 넣으면 해당 값(여기선 해당 User)을 찾아 반환합니다. 그런데 그 값을 수도 있잖아요. 그래서Optional
타입으로 반환합니다. 그 말은orElseThrow()
나orElse()
을 통해 처리해줘야 한다는 것이죠. Model에 담을 때는Optional
으로 바로 넣으면 값이 전달되지 않습니다.
// findAll() 사용 예 발췌 model.addAttribute("users", userRepository.findAll()); // findById() 사용 예 발췌 return userRepository.findById(id) .orElseThrow(() -> new IdNotFoundException("해당 id를 찾을 수 없습니다"));
- 처음에
findById()
와 PK 사용법을 모르고Iterable
타입으로 값을 어떻게 찾아야할지 고민을 많이 했네요.
- 이번 미션에서 사용한 메서드는 딱 2개였습니다.
그럼 DB테이블 및 Column들은 어떻게 정의할까요? 그 부분은 위의 예(UserRepository
)를 이어서 생각하면 User객체에서 정의합니다. 사실 순서상 뒤늦게 설명드리긴 하지만 User
클래스 내에 DB속성값을 가장 먼저 정의해두어야 합니다. 그래야 그 속성 설정 값 바탕으로 Controller에서 데이터를 처리할 수 있기 때문이죠(예를들어 PK를 통해 해당 객체를 가져오는 부분).
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true, length = 20)
private String userId;
@Column(nullable = false, length = 40)
private String password;
@Column(nullable = false, length = 30)
private String name;
@Column(nullable = false, length = 30)
private String email;
}
우선 @Entitity
을 통해 해당 테이블을 지정해두고 @Id
로는 PK를 정할 수 있습니다. 여기서 id가 PK로 테이블의 고유한 값을 담당하고 있네요. @GeneratedValue(strategy = GenerationType.IDENTITY)
은 자동 증가된 값을 알아서 채워넣을 수 있도록 하는 설정입니다. 그리고 @Column
에노테이션 옆 괄호 안에 세부설정까지 한 것을 볼 수 있습니다.
그런데 기능파악을 위해 여러 테스트를 하다가 PK가 아닌 속성에 대해 @GeneratedValue(strategy = GenerationType.IDENTITY)
을 설정하였을 때 증가된 수가 자동으로 넣어지지 않는 것을 관찰할 수 있었습니다. PK가 아니면 이 속성이 제대로 작동하지 않는 것일까요? 이 부분은 좀 더 알아봐야겠습니다.
오늘 추가적으로 공부한 부분
'TIL' 카테고리의 다른 글
Today's Dev Notes(2018-11-19) (0) | 2018.11.19 |
---|---|
Today's Dev Notes(2018-11-18) (0) | 2018.11.18 |
Today's Dev Notes(2018-11-15) (0) | 2018.11.15 |
Today's Dev Notes(2018-11-14) (1) | 2018.11.14 |
Today's Dev Notes(2018-11-13) (0) | 2018.11.14 |