Project 통합택배조회 api 05편 (네번째 구현-vue,로직개선)
Created Time: September 16, 2022 6:11 PM
Last Edited Time: September 21, 2022 3:09 PM
현재 구조
당장할것
- vue로 동적 페이지 개발 → 백엔드와 프론트엔드 나누기
- 재설계
- 크롤링데이터 get 처리.. “”null???
- https://kth990303.tistory.com/279
- 함수가 어떤걸 반환해야하는건지
null 처리 ? 객체로 valid처리? - CUpost확인하기
364321267646,364318961463 됨
22096084054 → 이런거 들어오면 오류 처리, 막을 방법필요 → 편의점끼리 택배 운송장
- 멀티 모듈 정리하기(build.gradle dependency정리)
- 21일 작성→ ppt랑 포트폴리오 → 동영상 → 약식 발표
시도해볼것
- link로 접속시 userid+postNumber로 간단한 유저 인증 후 검색기록 list로 제공하기
- 한번 scale-out해보기
- 많은 consumer와 provider를 docker로띄우고 연결
- 트레픽, 스트레스 테스트가능? → X
- 다른 택배사 추가하기 → provider 추가하기
HomeVue 만들기(프론트페이지)
왜?
현재 서비스는 8080포트로 직접 사용자가 servicehome으로 접속하였다. 따라서 API에서는 약속대로 JSON을 반환하였다. 이는 브라우저에 따라서 JSON을 렌더링하거나, 하지못했다.
또한 API에서 지원하는 새로고침 또한 활용할수없었다. → 가장 최근 정보를 반영하는 방법은 다시 카톡을 입력하는방법말고없었음
따라서 프론트 페이지를 만들고, 거기에서 servicehome API를 get과 post를 보내고 응답받는다. 한 페이지에서 새로고침도 가능하다.
즉, 프론트 및 백엔드로 나누므로써 원래 목적한 책임도 분리가능하다.
vue+nginx구성
vue를 그냥 npm serve run만 해서 돌리면되는거아닌가? 라는생각을 했다…근데 다들 nginx를 통해 구현을 하더라 이유를 살펴보니 vue만 실행했을때는 예상하지못하게 vue 빌드가 내려간다고..
그래서 아마 nginx가 포트포워딩에 강점과 static files를 서비스해주는것에도 강점을 가지고있으므로 nginx와 vue를 같이 서비스하는거같다
nginx는 2가지에 보통 쓰인다
첫번째 역할은 *웹서버의 역할은 *HTML, CSS, Javascript, 이미지와 같은 정보(staticfiles)를 웹 브라우저(Chrome, Iexplore, Opera, Firefox 등)에 전송하는것이다.
두번째 역할은 리버스 프록시(reverse proxy)인데, 한마디로 말하면 클라이언트는 가짜 서버에 요청(request)하면, 프록시 서버가 배후 서버(reverse server)로부터 데이터를 가져오는 역할을 한다. 여기서 프록시 서버가 Nginx, 리버스 서버가 응용프로그램 서버를 의미한다.
docker-compose 구조변경
나머지 설정
vue 프로젝트의 root밑에 Dockerfile 생성
vue create
vue create frontend
cd frontend
npm install vue-router —-save
Dockerfile
- 멀티빌드를 사용하여, node에서 vue를 빌드 시키고, 컨테이너 생성시 해당 이미지의 있는 파일들을 nginx로 COPY후 nginx를 실행하였다.
- 참고로 도커의 멀티 빌드를 사용했다. 따라서 build할때 용량과 막상 docker run 할때 용량은 다르고 축소시킬수있다.
1 | # build stage |
- docker-compose 내용 추가
1 | version: '3' |
vue-bootstrap
npm이용 설치
1 | npm install --save //bootstrap 설치이전 필수 /core |
main.js 내 import
1 | import { createApp } from 'vue' |
Vue에 기능넣기
스펙
- onepage동작으로 구성(내부망으로 API요청관건
- 초기접속 → get method로 homeservice로 API요청→ 해당url pathparameter에 대한 조회해서 가져오기
- 새로고침 기능 넣기 → post method로homeservice로 API요청 → 해당url pathparameter에 대한 데이터 갱신 요청후 → vue 페이지 alert(”결과보고”)→ reload() or fnGetPostDeatil() 호출 → 프론트에 데이터 반영완료
- 마이기록 조회 기능넣기 → 누르면 url path 변경하면서 /recodes 로 들어가며, homeservice API에 get method로 요청→ List 반환받아서 작성해줌
- 이렇게 구현하면, vue를 통해 접속하고 vue에서 내부망으로 접속홀수잇으므로
구현
PostDetail.vue
- recodes로 넘어갈때 params.userId를 query로 넘겨줌
1 | <script> |
Recodes.vue
1 | <script> |
PostEntity
PostDTO객체에서 이제 postCompany 값을 같는다
postCompany를 ENUM으로 처리를 String 또는 value 또는 converter로 할지 선택해야함
jpa의 postCompany Enum 처리 → string으로 DB에도 남기고싶기에 다음과같이 처리하였다.
- post entitiy에 추가
1 | (EnumType.STRING) |
위 정보에 맞게 dto들도 수정하였다.
추가로 이제 response용 ResponsePost를 DTO로 따로 만들어 응답하므로 내부 id값등의 불필요한 정보는 유저에게 주지않았다. 또한 postConpany 값마다의 name을 정해 name으로 반환하도록하였다
개선점
null반환?Optional반환?빈 객체반환? (???)
Student객체를 반환하는 책임 갖는 함수는 도대체 어떤것을 반환하는것이 더 좋은 방법일까?
return null
→ 호출한곳에서if null
처리가 필수다. 잘못하면 NullpointException가능return new Student();
빈 객체 반환 → null대신 쓴다면 에러 생성된 객체가 비어있는지 검사하는 로직 개별적구현..모든 객체 통일어려움 → 호출한쪽에서 NullpointException X- 빈 객체반환하여 해당 데이터가 존재하지않음을 보여줄때나 활용할때 사용하는것이 좋을듯하다.
return Optional.ofNullable(student);
Optional 객체반환 → 호출한 쪽에서.getOrDefault(new Student())
사용하면 null이들어가있어도 다른처리가능 → NullpointException X- Optional 방법은 호출자가 받은값은 비어있을수있음을 알수있기 때문에 권장!
- 하지만 Optional을 쓴다는것은 호출자가 매번 값을 체크해야함을 의미할수있기에 생각해서쓰자.(endpoint에서 쓰는게 좋을듯?→한번체크하면 담부터 Optional안쓰는게나을듯)
1 | Optional<Studnet> optionalWithStudent = Optional.of(convert(student)) //convert는 student객체 또는null반환하는 함수 |
호출자 입장에서의 Optional 활용
1 | Student resultstudent = optionalWithStudent.getOrDefault(new Student()) // get modified student or new student if condition inside convert() was not met |
1 | Optinal<Student> studentOptinal = convert(st);//convert가 student객체 또는null반환하는 함수 |
오류
nginx+vue 하위 경로 접속시 404오류
현상
메인페이지만 나오고 하위 경로는 404 에러
원인
Vue가 SPA이기 때문이다. Nginx는 정적 컨텐츠를 전달할 때, root 디렉터리에서 파일의 존재 여부를 찾는다.
‘http://{IP주소}:{포트번호}/mainpage’ 로 요청을 보내고 nginx 설정에서 root 디렉터리를 ‘/usr/share/nginx/html’ 이라고 했을 때, 해당 root 경로 안에서 mainpage.html 이라는 파일을 찾아 전달하려고 한다는 말이다.
하지만 나의 경우 하위 경로가 파일로 존재하는 것이 아니고 하나의 페이지에서 내용만 바뀌는 SPA 방식이기 때문에 존재하지 않는 파일이라는 의미에서 404 에러가 나타났던 것이다.
해결
아래 설정을 nginx.conf에 반영이 필요했다.
1 | location / { |
nginx+vue 405 에러
현상
docker-compose실행후 내부에서 vue에서의 axios를 활용한 get, post method 요청시 405에러 발생
해결
일단 요청 주소를 다시 확인
http://
부터 요청 주소 정확히 맞는지확인cross-origin 백엔드에서 허용 여부확인
- cross-origin(현 도메인과 다른 도메인으로 요청)시 preflight로 먼저 요청을 보낸후 지원하는 메서드, cross-origin 지원여부를 받고, 지원하지않는다면 본래의 요청은 보내지않고, 405 status 나온다!
서버 사이드 렌더링이 아니라서 vue에서 js로 axios를 통해 다시 보내는데, 문제는 브라우저입장에서 docker안에 내부망을 못쓴다.
- 그래서 8080으로 servicehome을 열고,,요청보냇더니 잘 읽어왔다.
requestparam 과 requestbody차이 잘보자
- requestparam으로 처리하고 이를 다음과같이 params로 처리하였다.
1
2
3this.$axios.post(
this.$homeserviceAPIUrl + "/"+this.$route.params.userId+"/"+this.$route.params.postNumber+"/",
{},{params: {"postCompany":this.postCompany}}
url encoding
상황
대한통운 params로 axios에서 처리하니 다음고같이 나타났다
CJ%EB%8C%80%ED%95%9C%ED%86%B5%EC%9A%B4
이를 spring에서 requestparams가 그대로 인식하여 오류가 났다.
원인
이유는 요청시 header에 urf-8을 넣어줘야 제대로 넣어줘야, 요청과 응답에서 인코딩제대로 가능하다.
해결
axios.post에서 header정보 추가해주기
'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8'
1 | this.$axios.post( |
vue-cli-service: not found
현상
Dockerfile
- dockerfile 빌드시 npm run build과정에서 에러가 뜨고,vue-cli-service: not found 였다.
1 | FROM node:lts-alpine as build-stage |
원인
package.json파일 내용이 원인이였다
기존은 devDependencies에있어서 개발 및 테스트 환경에서만 @vue/cli이 설치되었음 → Dockerfile에서의 npm run build처리시 vue/cli가 not found될수밖에없음
1 | "dependencies": { |
해결
- root폴더에 package.json @vue/cli 관련 코드 위치 변경
1 | "dependencies": { |
package.json에 대하여…
vue create 명령으로 생성된 node_modules 와 package.json 을 살펴본다.
package.json 파일에는 프로젝트 정보 및 scripts, dependencies, devDependencies 등의 속성이 기본적으로 포함되어 있다.
- scripts : 주로 사용할 명령어 모음
- dependencies : 해당 모듈에 필요한 라이브러리 모음 (프로덕션 환경))
- devDependencies : 해당 모듈에 필요한 라이브러리 모음 (개발 및 테스트 환경)
디펜던시를 패키지 관리자(npm, yarn, …)로부터 설치하고 나면 node_modules 디렉토리에 포함된다. 각종 테스트 도구나 컴파일러 관련 도구들은 개발 및 테스트 환경에서만 사용될 것이므로 devDependencies 속성에 포함할 것이다. 또한 빌드시 devDependencies 속성의 디펜던시들은 포함되지 않으므로 더 빠르고 가볍게 빌드가 가능하다. package.json 파일에 디펜던시를 정의한 후 npm 으로 설치해도 되고, npm 명령어(–save)로 설치 후에 package.json 파일의 디펜던시 속성을 업데이트 할 수도 있다.
예시: npm install axios —-save
디버깅시 해당주소 접속해도안됨
local에서 돌릴려하니까 안됨(SpringSecurity도 exclude함)
1 | 2022-09-21 10:39:31.747 INFO 65034 --- [nio-8081-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet' |
package 이슈가있었음. 멀티모듈할떄 잘못되어있었음
또한 @Pathvariable도 {test}로 { }가 안쳐저있었음
Invoke Error → RestController로 선언하지않아서 스프링 컨트롤러가 template찾고있었음.
provider택배 크롤링쪽에서의 오류
크롤링시 get 오류인
IndexOutOfBoundsException
나옴 이때는 try catch문으로 잡았음. → log찍고 끝