Project 통합택배조회 api 02편 (첫번째 구현)
Created Time: August 31, 2022 10:57 AM
Last Edited Time: September 16, 2022 2:43 PM
Tags: Java, Spring, Computer
왜?
첫번째 구현은 api서비스를 만들 것이며, MSA, kafka고려하여 서비스별 관계 설정후 구현할 것이다.
???
jsoup은 js가 처리안되어나오고, webclient는 tag들에 값이 들어가있는걸보면 된느거같은데??
- jsoup과 webclient의 차이가 뭘까…
- jsoup은 html parser를 활용하기위해 사용하는걸까?
- https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=qkrwkddl&logNo=30182929404
추후 timeout설정도 반드시 해주기(상대 서버가 죽었을가능성있음)
응답을 제대로 못받았을경우 어떻게 대처할지 처리하기
msa구성할때, service별로 분리한것이 중요한 개념
→ msa마다 db 가 없어도 상관없음.
message가 바뀌면 저장시도, message같다면 필요없이 해당 로우에 updateDate 를 변경 → message로 하면안될듯… message라면 바뀔가능성 있음. 아예 없을수도있음. 해당 택배회사의 택배 업데이트 날짜가 바뀌면 업데이트하는것이 나아보임
시퀀스 다이어그램
참고
대표적인 외부 택배조회 API의 JSON값
1 | { |
설계
DB 설계
RDB사용이유 및 연관관계 없는이유
- RDB를 사용하여 DATA의 일관성 확보(택배 조회시스템상 모두 비슷한 정보가짐)
- RDB강점인 관계는 설정 안함(이 서비스는 ID로만 거의 찾기 때문에 연관관계 이점없다고판단→ 한 테이블내에 모든 정보 찾을수있도록함→ ID의 카디널리티 높게해야함→ search 속도 높아야함(삭제기능없고, 추가만있으니 방향성확실))
아키텍처 설계
- 내 프로젝트 위치
- 내 프로젝트내 서비스별 아키택처
UML
- 해보기 하지만 먼저 구현해보는게 좋아보임
- 나중에 작성하기
Post Data field
- (PK) Id: ID 요청
- kakao_id: user 정보
- sender: 보내는이
- receiver: 받는 이
- message: detail한 메세지
- location: Hub → Hub
- status_data: 택배사의 기록 업데이트 날짜 (이것을 기준으로 새로운 데이터 생성할지 말지 판단해도될듯)
- updated_time : 내 DB에 업데이트된시간
외부 택배사 api 뜯기
대한 통운
request조건
같은 시기에 발급된 세션값+csrf값을 넣어주면 모든 요청에서 가능했음(나머지 인자 필요없음)
- 쿠키
- sessionid값
1 | JSESSIONID=68DC345A45962C2AEA58861B86E2E913.front12; Path=/; HttpOnly; |
- body
- csrf값
- paramInvcNo 값 (=운동장번호값)
1 | _csrf=e1030947-f0f8-48a8-8def-d7eea2e6e8d3¶mInvcNo=364321198184 |
csrf공격 방지 동작중…
csrf토큰역할: 요청폼이 올바른 폼인지 아니면 다른곳에서 만들어진 폼인지 구분
csrf공격때문에 생긴 방법으로 세션으로 인증되어있을때, 다른 사이트로 접속하게되면, 정보를 수정해서 타인이 보낼수있다. 이를 방지하기 위해csrf를 각 세션별로 가지고있고, 이를 사용자의 요청에 hidden으로 숨겨놓고 csrf까지 인증해야 정상적인 요청으로본다.
CUpost
cu는 iframe을 사용하고있었다.
request조건
- get parameter
- pTdNor값(=운송장번호)
DB
@EnableJpaAuditing
jpa사용시
@EntityListeners(AuditingEntityListener.class)
@createddate 사용시
application.properties
1 | # DB ?? |
Controller별 구현
- postDBservice관련부분은 추후 msa에 따라 빠질것
처음 요청하는 uri
- postDBservice관련부분은 추후 msa에 따라 빠질것
1 | //카카오톡으로 처음 요청한 경우 링크를 반환함! |
내 서버에서 반환한 uri
1 | // 내 서버가 응답한 link경로로 접근한경우 |
새로고침할때 uri
- 이를 post로 구현하였다. → 필요한 이유는 새로고침을 따로 만들고 쓰기 때문에, 다른기능과 통합되어 자동을 일어나는 불필요한 새로고침 요청을 축소시키는 역할을 한다.
1 | // 새로고침 만들기 post->인자 가져와서 이미 모든 필드값같다면 modified_data만 바꿔주기 |
service
ValidRequest
- 요청에서 데이터 받아서 정보 추출하는 역할 하는클래스
- 현재 카카오톡과 연동되지않아서, 일단 이렇게 구현했다.
1 |
|
PostManager
- postmanager는 외부 택배 api에 대해 지원하는지 판단후, 응답을 받고 이를 PostDto로 반환하는 책임을 진다.
1 |
|
PostDbService
1 |
|
Provider들
- 이는 외부 택배 조회 service들을 각자 빈 등록해서 사용하였다.
문제 해결
Jsoup json 에러
문제점
org.jsoup.UnsupportedMimeTypeException: Unhandled content type. Must be text/*, application/xml, or application/xhtml+
애석하게도, jsoup은 html parser로 만들어졌고, 따라서 json content-type을 support하지않는다.
해결책
.ignoreContentType(true)
를 통해 강제로 일단 파싱하여, json 파싱이가능한 ObjectMapper()를 통해 jsoup의 document에서 body().text()반환받은후 파싱을 진행하였다.
1 | public PostDto get(String postNumber) { |
조회 빈이 2개이상일때 문제
문제점
provider의 인터페이스의 구현체인 택배 크롤링 provider들은 ProviderManager 에서 각자 주입되어야했다. 하지만 이는 DI의 원칙을 위배한것이므로 다음과 같이 해결했다
해결
- List
해당 타입의 모든 스프링빈 반환 특징을 이용하여 주입하였다.
1 |
|
추가 정보
- @Autowired를 하면 스프링 빈에 타입을 조회로 하여 주입된다. 따라서, 같은 타입이 두개라면 문제가 발생한다.
- 해결책은 많다.
- @Autowired 필드 명 매칭
- @Qualifier @Qualifier끼리 매칭 빈 이름 매칭
- @Primary 사용
- Map<String, DiscountPolicy> 해당 타입의 모든 스프링 빈과 해당 값 반환 → 없다면 빈 List반환
- List
해당 타입의 모든 스프링빈 반환 →없다면 빈 List반환