이번 강의에서는
Angular 웹 애플리케이션에서
코드들이 변하는 과정을 깊이있게 설명해보려고 합니다
그래야 여러분들이 적어도
웹 애플리케이션 안에서 무슨 일이 일어나고 있는지와
백엔드와의
소통은 어떻게 이루어지는지
UI의 로직들은 어디에 적는지 알게 될 것입니다
Angular 애플리케이션에 관해 궁금한 것이 많을 수 있습니다
여러분들의 이해를 돕기 위해
이 프로젝트 안에서 코드들이 어떻게 변하는지 알려드리겠습니다
Spring Boot 웹 애플리케이션에서
콘트롤러라는 기능으로
비지니스 로직을 쓸 수 있는 것처럼
아주 유사하게 Angular에도 비슷한 요소들이 있습니다
여길 보시면 제가 모듈화 해놓은
UI 애플리케이션의 모든 코드들이 있습니다
accounts, cards, balance 같은 부분에 쓰입니다
contact, dashboard, header, home
이 요소들이 전부
Angular 애플리케이션 안에 있습니다
언제든 여러분이 질문이 있을 때
loans에 관련된 기능적인 부분이라든가
notices(공지), header(헤더), contact(콘택트) 등
그에 맞는 요소에 들어가 보면 됩니다
각 요소 안에는
4개의 파일이 있습니다
.spec.ts로 끝나는 파일들은
Angular의 테스팅 파일이며
새로운 요소를 생성할 때마다 자동으로 생성됩니다
그러므로 이 테스팅 파일들을 무시해도 좋습니다
다음으로 보게 될 파일은 .html 입니다
.html 안에서는 HTML 코드들을 볼 수 있으며
그와 더불어
Angular syntax들이 종종 보입니다
이 Angular syntax 들은
전체 과정 내내 강조할 것입니다
특히 백엔드로부터 불러온 데이터를 표시할 때 중요합니다
HTML이 있다는 건 물론 이 HTML도 CSS를 필요로 한다는 것입니다
그렇기 때문에 각 요소 안에 CSS 파일도 포함되어 있습니다
그리고 요소의 마지막 파일은
.component.ts 입니다
이 요소 클래스 안에서만
우리가 가진 대부분의 비지니스 로직들을 쓰게 됩니다
HomeComponent를 보면
아무 로직도 없습니다
왜냐하면 이 요소의 목적은
그저 홈페이지를 보여주는 것이기 때문입니다
여기 보이는 요소의 스타일은
이 CSS 클래스로부터 받습니다
구조는 이 HTML 파일으로부터 받는 것이며
그리고 요소가 가진 선택자
app-home이 있습니다
이 선택자가 사용되면
그러니까 app-home이 사용되면
HTML 파일 안에 있는 UI 코드들은 CSS와 함께 보여집니다
그게 선택자를 쓰는 목적입니다
그래서 각 요소들에게는 선택자가 있고
언제든 요소에서 요소로
탐색할 때
알맞는 HTML 파일이 보여집니다
요소 다음으로는 모델(model)이 있습니다
모델에는
간단한 POJO 클래스처럼 필드들이 있습니다
그리고 이 모델 클래스들을 통해서만
백엔드와 소통하며
백엔드로부터 데이터를 가져올 것입니다
이 모델에 대해서 자세히 다뤄보려고 합니다
특히
백엔드와 소통할 때 말입니다
그리고 이 services 파일 안에는 서비스 패키지들이 있습니다
백엔드와 소통을 할 때면
그에 필요한 모든 코드들은
이 services.ts 파일에 있습니다
Angular에서는 모든 것은 TypeScript(.ts)로 쓰여야 하며
일반 JavaScript(.js)를 사용해서는 안 됩니다
컴파일 과정에서 이 TypeScript가
JavaScript로 변환되는 것입니다
브라우저들은 TypeScript를 이해할 수 없고
JavaScript만 이해할 수 있습니다
TypeScript는 JavaScript의 고급 버전입니다
그래서 .services 파일을 보면
로그인 파일도 마찬가지로 login.service.ts 라는 파일이 있습니다
이 서비스 파일을 보면
백엔드를 불러오는 로직이 있는 걸 볼 수 있습니다
여기에서 get 함수를 사용하여 URL을 요청합니다
루트 URL을 환경 파일에서 불러올 수 있도록
여기서 루트 URL은 저의 백엔드 애플리케이션의 URL입니다
localhost:8080 입니다
그 다음에 또 다른 상수가 있는데
AppConstants. 를 통해 불러오고 있습니다
이것을 열어봅시다
/user 가 endpoint URL 입니다
지금 우리에게 없는 이 서비스는
백엔드 애플리케이션에서 만들어 보도록 하겠습니다
누구든 내 애플리케이션에 로그인을 시도하면
이 서비스를 불러올 것입니다
그리고 보시다시피 다른 조건들도 있는데
예를 들어 contact 서비스 라든가
myAccount, myBalance, myLoans, myCards 와 notices 등등
제 워크스페이스 안에 있는 상수를 잘 보면
REST 서비스의 호출이
UI 애플리케이션으로부터 어디에서 발생되는지 알 수 있습니다
검색 버튼을 누르고
검색을 하면
dashboard.service.ts 에서 찾은 결과들이 보여집니다
메소드들도 전부 보이고
예를 들어 이런 getAccountDetails 메소드들도
accounts API를 불러오는 것입니다
balance API와 loans API를 불러오는 것과 마찬가지입니다
cards API, notices API와 contact API도 전부 같습니다
여기까지가 .services 폴더 안에 있는 내용이었습니다
그리고 한 가지 더 알아야 할 중요한 파일은
app-routing.module 입니다
이 파일에 요소들과 함께
경로를 정의해 두었습니다
만약 누군가
localhost:4200를 아무 경로 없이 접속하려 한다면
다시 /home 경로로 재지정될 것입니다
언제든 누군가 /home으로 재지정되면
여기 적힌 경로와
HomeComponent에 상응하는 요소가 불러와 질 것입니다
그리고 다른 부분들
login, contact도 매우 비슷합니다
각 경로에 상응하는 요소들이 있습니다
엔드 유저가 로그인 버튼을 눌렀다고 가정해 봅시다
브라우저를 통해 보여드리겠습니다
지금 앱에서 로그인 버튼을 클릭하는 게 보이시죠?
제가 로그인 버튼을 클릭하자 마자
URL이 /login 로 바뀝니다
그리고 제가 클릭하는 순간
HTML 페이지를 받게 됩니다
이 과정이 어떻게 이루어지는 건지 봅시다
제가 헤더(header)에 있는
로그인을 버튼을 클릭합니다
그래서 header.component.html이 열립니다
여기 보면
로그인 버튼이 있는데
이 버튼이 라우터 링크, /login를 불러옵니다
그러면 로그인 경로를 위해
이 설정에 오게 되고
그리고 그것이 로그인 요소를 불러오는 것입니다
다시 돌아가서
로그인 요소에 무엇이 있었는지 확인해 보면
HTML 파일이 있고 login.component.css이 있었습니다
그러므로 이 파일들 안에 있는 모든 코드가 표시됩니다
그리고 HTML과 함께
app-header도 있습니다
만약 검색을
app-header라고 제 워크스페이스에 해보면
그건 제 헤더 요소로부터 불러와집니다
header.component.ts를 열어 봅시다
열어 보면
이게 제 헤더 요소의 선택자입니다
만약 누군가 이 app-header를 불러오려 한다면
header.component.html 안에 있는
HTML과 UI 코드들은 전부
제가 불러오려는 HTML 파일에 첨부됩니다
이제 로그인 요소의 내부가 보이는데
먼저 헤더를 불러올 거고
그 다음에 로그인과 관련된 HTML 코드들을 불러올 것입니다
그래서 로그인 페이지에
헤더가 먼저 보이고
그 다음 로그인과 관련된 UI 코드들이 보입니다
물론 코드들은 전부 HTML 안에 있습니다
Sign In (로그인)버튼을 보면
Sign in 버튼에
type은 submit이며 이는 저의 양식을 제출해 줍니다
그리고 submit (제출)에서
validateUser라는 함수를 불러오라고 하는 것입니다
이 함수는 당연히 로그인과 관련된
요소 안에 있습니다
다시 login.component.ts 를 확인해 보면
validateUser라는 함수가 있습니다
이 함수를 통해서
로그인 서비스 안에 있는
validateLoginDetails 함수를 불러오는 것입니다
그걸 클릭하면
백엔드로 가는
get API 요청을 만드는 것입니다
validateUser 안에 있는
함수를 살펴보면
그저 로그인 서비스 안에
사용 가능한 함수를 불러오는 것 뿐입니다
이 메소드는 REST API를 불러오기 때문에
저는 등록(subscribe)을 하려고 합니다
등록은 Angular의 개념으로써
백엔드 서버와
소통할 때 사용합니다
이는 비동기식 소통을 지원합니다
언제든 백엔드로부터 응답을 받으면
제가 등록하여 쓴 코드들이
전부 실행됩니다
보시다시피 저는 백엔드로부터 받은
응답 데이터를 수락하고
그 바디(body)를 가져오는 것입니다
그런 다음 여기에 비지니스 로직을 실행합니다
그리고 마지막으로 로그인이 성공적일 때
유저를 라우트 그러니까 대시보드로 재이동 시킵니다
언제든 유저를 새로운 경로로
안내할 때는
제 파일로 돌아오게 됩니다
이름은 app-routing.module.ts 입니다
대시보드를 위해서는
dashboardComponent 라는 요소를 불러올 것입니다
그리고 여기 보이는 canActivate 같은 것들은
보호를 위한 역할이며
엔드 유저들이 로그인 없이 접속하지 못하도록 합니다
특정 부분들 예를 들어 home
login, contact, notices, log out
이것들은 전부 공용의 목적으로써 누구든 접속할 수 있습니다
하지만 dashboard, myAccount, myBalance, myLoans, and myCards 같은 부분들은
오직 엔드 유저가 로그인 했을 경우에만 접속할 수 있습니다
그래서 이 canActivate를 쓰면
AuthActivateRouteGuard 안에
특정 로직들을 정의합니다
그걸 클릭해서
간단한 확인을 해보겠습니다
userDetails를
sessionStorage에서 받으려 하는데
sessionStorage에 userDetails가 있거나
유저 객체이 null이 아닐 경우
true을 반환하고 반대의 경우 false을 반환합니다
무슨 뜻이냐면 언제든 유저가 로그인 했을 때
유저 정보가
sessionStorage 안에 있을 거라는 것입니다
login.component.ts 를 확인해 보면
응답을 받자마자
객체이 생성되고
그게 sessionStorage 안에 있는 userDetails입니다
이는 오직 인증이 완료된 후에만
이 정보들이
전용 sessionStorage에 저장된다는 뜻입니다
그것과 함께 authStatus와
로그인 요소 안에 있는 AUTH 값도 함께 저장 중입니다
그러니까 이것의 목적은 오직 이 AUTH 값을 사용해서만
헤더에 무엇이 표시될지 결정하는 것입니다
header.component.ts 로 가보면
header.component.ts 안에
헤더에 관련된 HTML이 있습니다
이 HTML을 눌러보겠습니다
여기 보면 유저가 로그인 했을 때
authStatus가 AUTH가 되고 아닐 경우 AUTH가 아닙니다
그래서 이 ngIf를 사용하여
(Angular의 if 조건과 같은)
authStatus 값이 AUTH일 경우
대시보드와 로그아웃만 표시하라고 명령하는 것입니다
반대의 경우 공용 링크들만 표시하도록 하는 것입니다
예를 들어 home, login, contact, notices과 같은
이런 방식으로 정보들을
컨트롤하고 게시하는 것입니다
마지막으로 딱 하나 더
인터셉터에 관한 것만 나누도록 하겠습니다
인터셉터 파일은
Angular 애플리케이션 안에 있습니다
인터셉터 파일의 목적은
백엔드로 가는 모든 요청들을
가로채는 것 입니다
제일 먼저
userdetails를 sessionStorage로부터 받으려 하고
유저 객체에 동일한 것을 할당합니다
그리고 이 유저 객체가 null이 아니고
비밀번호와 이메일도 있을 경우
그 뜻은 유저가
애플리케이션에 아주 처음 로그인한다는 것입니다
그럼 그때는 오로지 비밀번호와 이메일만 있습니다
이 상황에서는
그저 Authorization 헤더와 Basic을
그 다음으로는 이메일과 비밀번호를 차례로 보내려는 겁니다
이건 http의 기본 인증과도 같습니다
그리고 다른 모든 경우에는
그러니까 비밀번호와 이메일이 비어있을 때는
유저를 재인증하지 않을 겁니다
왜냐하면 두 번째부터 계속
인증이 이미 이루어졌고
이 authorization 헤더를 보낼 필요가 없습니다
여러분들이 이런 질문을 할 수도 있습니다
그럼 Spring Boot는 유저가 인증되었는지 아닌지 어떻게 알 수 있을까요?
그 부분은 dashboard.service.ts 에 가면
여러 REST 서비스들이 있는데
그 중에서도 dashboard.service.ts 를 봅시다
벡엔드에서 REST API를 부를 때마다
(security API들을 부르기 위해)
withCredentials의 값을 true이라고 전달합니다
이 부분을 더 설명하자면
withCredentials가 true일 때
Angular에게
갖고 있는 쿠키들이나
Session ID 또는 토큰들을
백엔드로부터 찾아 달라는 요청입니다
그래야 Spring Security가
인증이 이미 이루어졌는지 아닌지 이해할 수 있습니다
문의하기와 공지사항 같은 공공 API는
withCredential의 값을 true로 반환하지 않습니다
왜냐하면 그것들은 인증이 필요 없기 때문입니다
보시다시피
observe를 불러오는 것은 response를 불러오는 것과 같다는 것을 알 수 있습니다
이렇게 observe가 response일 경우
백엔드 서버에게
응답을 전부 달라고 요청합니다
헤더만도 아니고 바디만도 아니고
전부 필요하다는 것입니다
이게 observe가 response로 쓰일 때
소통하는 방식입니다
여기까지 Angular 애플리케이션에서
중요한 클래스들과
로직들에 대해서 다뤄보았습니다
물론 추후에 다시 한 번 돌아와서
다룰 예정입니다
그땐 특정한 상황들에서 일 것입니다
하지만 이제 여러분들이 Angular 애플리케이션에 있는 것들을
어느 정도 어려운 수준까지 이해했다고 생각합니다
만약 확실히 이해가 가지 않았더라도 걱정하지 마시기 바랍니다
여러분은 Angular를 배우러 온 게 아니기 때문입니다
우리는 Spring Security를 배우려는 것입니다
그래도 여러분들이 적어도
Angular 애플리케이션 내에서의
중요한 코드 변환에 대해서라도 이해하셨길 바랍니다
감사합니다 다음 강의 때 뵙겠습니다
수고하셨습니다