이번 강의에서는
백엔드 애플리케이션을 수정해보도록 하겠습니다
이전 강의에서 생성한
새로운 데이터의 틀을 수용하기 위함입니다
강의를 시작하기 전에
제가 미리 수정 작업을 해놓았습니다
여러분의 시간은 소중하기 때문입니다
그럼 이제 빠르게 변경된 내용에 대해서 다루고
질문이 있다면
언제든 확인할 수 있는 코드가
GitHub 리포지터리에 있습니다
그래도 해결되지 않은 질문들은
제게 직접 남기실 수 있습니다
그건 Q&A 포럼을 이용하시기 바랍니다
가장 먼저 수정한 내용은
우리가 생성한 각 테이블에
새로운 엔터티(Entity) 클래스들을 생성했다는 것입니다
예를 들어 accounts 테이블을 보면
이게 엔터티 클래스고 그 안에
필요한 필드들과
열 이름들을 생성해놨습니다
그리고 비슷하게
account_transactions도 생성했습니다
테이블과 열 주석을
정확하게 사용할 수 있습니다
table_name을 정의해야 할 때도 그렇고
열 이름을 정의해야 할 때도 마찬가지입니다
하지만 열 이름이 굉장히 간단하다면
한 글자로 짓는다든지 그래서
필드 이름과 잘 매칭된다면 주석은 선택사항입니다
이런 경우에서도 주석은 선택사항이며
열 이름은 transaction_id입니다
Spring Data JPA는 tranasaction_id라는 이름을 이해하고
그 값을 이 필드에서 찾아낼 수 있을 만큼 똑똑합니다
그럼에도 제가 열과 테이블 주석에 대해 언급한 이유는
코드의 가독성을 높히기 위함입니다
Cards도 마찬가지로
Contacts를 위한 엔터티 클래스를 생성했고
Customer에는 이미 엔터티가 있었습니다
최신 열에 기반하여 수정 작업을 했는데
예를 들어 id 열 대신
Customer 안에 customer_id를
기본 키 열로 사용합니다
이런 식으로 매핑을 진행했습니다
이 id 필드는 customer_id 열이 되었고
또 새로운 열들도 도입되었습니다
name, email, mobile_number, pwd, role, create_dt 같은 것들 말입니다
그리고 모든 열들과
연관된 필드들을 만들었습니다
그래야 엔터티 클래스들이 깔끔하고
심플하기 때문입니다
쉽게 이해할 수 있습니다
엔터티 클래스들이 우리가 만든 데이터베이스 구조와
매칭된다는 사실을 이해해야 합니다
모델(Model) 클래스들을 만들고 나면
레포지토리 패키지 안에 필요한
레포지토리 인터페이스들도 생성해야 합니다
AccountsRepository 안에서
CrudRepository를 연장 시키고
보시다시피
유저가 로그인할 때면
그의 계좌(account) 정보를
findByCustomerId를 통해 받으려는 것입니다
accounts와 customer 테이블은
외래키가 있기 때문입니다
어떻게 customer id를 알 수 있냐면
로그인이 끝난후에는
엔드 유저의 customer id를
쉽게 이해할 수 있습니다
마찬가지로 account_transaction도
동일하게 작업해주겠습니다
findByCustomerId라는 이름을 가진 메소드와 함께
transaction_date가 내림차 순으로
정렬되도록 합니다
메소드에 이 이름 규칙을 따르면
Spring Data JPA가 알아서 SQL 쿼리 안에
클래스대로 정렬하고 transaction_date도
알아서 내림차순으로 정렬해줍니다
만약 여러분이 Spring Data JPA에서
메소드 이름과 쿼리 컨셉에 대해 관심이 있다면
제 Spring 과정을 들어보시기 바랍니다
마찬가지로 CardsRepository에 findByCustomerId라는 메소드가 있습니다
ContactRepository에는 아무 메소드도 없습니다
왜냐하면 지금까지는
프론트엔드부터 백엔드로 데이터를
전달하는 상황만 있었기 때문입니다
아직 우리는 연락처(contact) 정보를 데이터베이스에서
가져와야 하는 상황은 없었습니다
그렇기 때문에 비어있는 것입니다
CustomerRepository 안에는
이미 findByEmail 라는 메소드가 있고
이 레포지토리는 이전 섹션에서도 사용한
오랜 레포지토리입니다
LoansRepository에는
findByCustomerID가 있고
starting_date의 정렬또한 내림차순이며
AccountsTransactionsRepository와 매우 유사합니다
이제 NoticeRepository로 넘어가 봅시다
새로운 메소드를 생성했고
이름은 findAllActiveNotices 입니다
언제든 이 메소드를 불러오면
이 쿼리가 백엔드 테이블에서 실행되기를 원합니다
그러므로 보시다시피 쿼리 안에 JPQL을 사용했습니다
이것은 직접 SQL을 호출하지 않는 것입니다
JPQL은 SQL 포맷으로써
엔터티 클래스와 함께 쿼리를 작성하는 것을 도와줍니다
그러니 여기에 테이블 이름은 언급하는 대신에
엔터티 클래스를 언급할 수 있으면 비슷하게
열 이름을 직접 언급하는 대신
엔터티 클래스 안에 있는 필드 이름을
언급할 수 있습니다
notice 엔터티 안에 있는
필드 이름들은 noticeBegDt와
noticeEndDt입니다
이 쿼리를 통해 얻으려는 것은
notice 시작 날짜와 notice 마지막 날짜 사이에 있는
현재 날짜들을 전부 가져오는 것입니다
이 뜻은 기간이 지난 notice들은
보고 싶지 않다는 것입니다
시작 날짜든 끝나는 날짜든
현재 날짜 사이에 있다면 그것만 표시하고 싶습니다
그래서 메소드 이름이 findAllActiveNotices인 것입니다
그러므로 여긴 지정된 메소드 쿼리 방식을 사용하지 않고
왜냐하면 이 이름은
Spring Data JPA가 SQL을 자동으로 생성할 수 없기 때문에
제가 쿼리 주석 안에 언급한 값의
쿼리를 실행해 달라고
직접 힌트를 주는 것입니다
이렇게 레포지토리 클래스들을
전부 생성해보았습니다
이제 빠르게 Controller 클래스들을 확인해보면
AccountController처럼
프론트엔드 애플리케이션으로부터
customer id를 받으려고 합니다
그리고 customer id를 기반으로
계좌(account) 정보들을 가져오고
동일하게 반환합니다
BalanceController도 마찬가지로
여기서 id를 받고
accounts transaction 테이블을 상대로
쿼리를 실행할 겁니다
그리고 UI에 동일한 값을 반환합니다
cards도 매우 비슷한데
특정 customer id를 위해
cards의 리스트를 가져올 겁니다
ContactController 안에
프론트에서 가져온 정보들을
저장할 것입니다
누구든 문의하기 페이지에 정보를 제출하면
그 정보들이
후 매핑을 통해 들어오면
enter contact 객체를 가지게 됩니다
연락처(contact) 정보를 데이터베이스에
저장하려고 할 때면 이 메소드를 통해
contact id가 생성되는것이 바로 getServiceReqNumber입니다
이 contact id 열은 기본키 열로
contact 테이블 안에 있으며 이 contact id들을 위해서는
매번 랜덤으로
ServiceReqNumber를 생성합니다
(이 ranNum 함수가 필요합니다)
그것을 SR 값에 고정시키고
이것이 ServiceReqNumber라는 것을 나타냅니다
마찬가지로 데이터베이스 안에 보관합니다
지금 기본키를 수동으로
생성해야하는 상황이기 때문에
contact 엔터티를 다시 확인해 보면
이 기본키 주석이
자동으로 생성되는 sequence number를 사용하지 않고 있습니다
customer 엔터티도 마찬가지로
자동으로 할당되는 sequence 값을 사용하고 있는데
여기서는
이 generatedValue and genericGenerator를 활용합니다
하지만 contact 엔터티에서는 이를 사용하지 않을 겁니다
왜냐하면 ContactController는
제가 직접 수동적으로 작업을 하고
이 계산된 contact id는
제가 쓴 로직에 기반하며
getServiceReqNumber 안에 제공됩니다
LoansController에서는
특정 customer id를 위한
loans 정보를 모두 불러오고
다음 LoginController에는
이미 등록 메소드가 있고
이 등록 메소드 안에는
어떠한 수정도 하지 않았습니다
대신 REST API 서비스로 새로운 메소드를 만들었는데
이름은 /user입니다
이 API는 엔드 유저의
로그인 동작이 시작될 때마다
프론트엔드로부터 불러와집니다
이 메소드 안에서는
customer 테이블에서 고객(customer) 정보를 불러오고
이는 엔드 유저의 이메일을
기반으로 합니다
나중에 이 로직에 대해 한 번 더 설명해드릴 겁니다
로그인 운영법을 배워야 할 때나
Angular 애플리케이션을 사용할 때 말입니다
지금은
이 REST 서비스가
로그인 동작에서 불러와지고
고객(customer) 정보들이 데이터베이스에서
UI 애플리케이션에서 가져와지고 보내진다고
알아두시기 바랍니다
마지막으로 NoticesController 클래스가
이 클래스 안에 있고
findAllActiveNotices 메소드를 불러와서
모든 notice들을 가져오려는 겁니다
이 메소드는
notices를 불러오면
응답 내에서 전달합니다
공지사항(notices) 정보와 함께
캐시와 관련된 헤더 정보도 전달하며
그 뜻은
어떤 공지사항(notices) 정보를 보내든
다음 60초 동안 그것을 이용하라는 의미입니다
만약 유저가 60초 이내로 공지사항 페이지를 새로고침하면
UI 앱에서 REST API 요청은 이루어지지 않습니다
대신
캐시 안에 이미 들어있는
공지사항(notices) 정보를 사용하기 위해
60초 동안은 유효합니다
이 동작은 추후 강의에서
공지사항 페이지를 확인할 때도 볼 수 있습니다
마지막으로 강조하고 싶은 것은
ProjectSecurityConfig 안에
우리가 만든 서비스
/user가 인증되어 있기를 바랍니다
permit all()은 하지 않습니다
이것이 왜 안전한지
permitall()은 왜 아닌지 추후 강의에서 설명드리겠습니다
여기까지가 Spring Boot 웹 애플케이션에서
수정 작업을 한 내용입니다
서두르지 말고 이와 같은 작업을
여러분의 Spring Boot 웹 애플케이션에도 적용해보시길 바랍니다
질문이 있을 땐
언제나 GitHub 리포지터리에 있는
코드들을 참고하시면 됩니다
오늘 강의도 잘 이해하셨길 바랍니다
다음 강의에서는 웹 어플리케이션을 시작하고
회원가입 과정을 테스트하며
Postman을 통해 잘 작동되는지 확인해보겠습니다
감사합니다 다음 강의에서 뵙겠습니다