[꼼꼼한 개발자] 꼼코더
42. [개발일지] - [피파 온라인 4 프로젝트] - 07. 유저의 경기 종류별 역대 최고 등급 조회기능 개발 (2) (DTO의 등장, 서비스, 구현체) 본문
42. [개발일지] - [피파 온라인 4 프로젝트] - 07. 유저의 경기 종류별 역대 최고 등급 조회기능 개발 (2) (DTO의 등장, 서비스, 구현체)
꼼코더 2023. 5. 17. 16:11📑 개발할 기능 순서(이전 글 내용 요약)
- 유저 고유 식별자로 역대 최고 등급 조회
- 피파의 메타 데이터 조회 (매치 종류, 등급 식별자)
- 유저의 matchType(경기 종류), division(최고 티어)의 식별 번호들을 피파 메타 데이터와 매칭시켜 값을 추출
- 추출한 데이터를 경기당 1개의 객체(DTO)로 변환 후 리스트로(감독, 공식) 모아서 화면에 표현
💻 기능 개발 전 DTO 작성
먼저 보면 API 결과 값이 보인다.
이 뜻은 곧 내가 만들어야 할 DTO의 인터페이스라고 할 수 있다.
DTO의 필요성은 간단하게 설명하자면(추후 개별 글 작성)
DTO 객체를 사용함으로써 클라이언트에게 필요한 정보만 전송할 수 있다.
3가지의 DTO를 작성해 보자. (DivisionDTO, MatchTypeDTO, UserTearHistoryDTO)
// 경기 종류와 종류를 표현하는 번호 정보를 담아 전달하는 DTO
@Getter
@Setter
public class MatchTypeDTO {
private int matchType; // 경기 종류 번호 > ex) 50
private String desc; // 경기 종류 이름 > ex) 공식경기
}
// 티어 정보를 담는 데이터 전송 객체(DTO)
@Getter
@Setter
public class DivisionDTO {
private int divisionId; // 티어 식별 아이디
private String divisionName; // 티어 이름
}
// 유저의 경기별 최고티어 정보를 담아 전달하는 DTO 객체
@Getter
@Setter
@NoArgsConstructor
public class UserTearHistoryDTO {
private String matchType; // 경기 종류
private String division; // 최고 티어
private String achievementDate; // 달성 날짜
}
이제 전달 객체를 작성했으니 기능개발로 들어가 보자.!
🧑🏻💻 1번) 역대 최고 등급 조회 (기본 기능만)
유저 고유 식별자로 역대 최고 등급 조회 기능을 작성한다.
요청 후 데이터를 가져오는 기능을 구현해 보자.
FifaUserService, FifaUserServiceImpl (인터페이스, 구현체) 코드 추가
// ----인터페이스----
List<UserMatchHistoryDTO> getUserTearHistoryList(String accessId); // 유저 경기별 역대 최고 등급 조회
// -----구현체-----
// 유저 경기별 역대 최고 등급 조회
public List<UserMatchHistoryDTO> getUserTearHistoryList(String accessId) {
String url = "https://api.nexon.co.kr/fifaonline4/v1.0/users/" + accessId + "/maxdivision";
headers.set("Authorization", apiKey.getKey()); // Authorization 정보를 담아서 API에 인증을 하기위해 api key값을 헤더 객체에 저장
HttpEntity<String> entity = new HttpEntity<>("UserMacthHistory", headers); // HTTP 요청의 본문(헤더도 함께 가능) 정보를 담아서 보낼 수 있는 객체 생성
List<UserMatchHistoryDTO> userMatchHistoryDTOList = new ArrayList<>();
// HTTP 요청을 보내고 응답을 받아오는 RestTemplate 객체의 exchange() 메소드를 호출
// 유저 경기별 역대 최고 등급 조회 결과 > [{"matchType":50,"division":800,"achievementDate":"2023-05-12T01:03:34"},{"matchType":52,"division":1100,"achievementDate":"2021-03-01T18:42:03"}]
ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
}
🧑🏻💻 2번) 피파의 메타 데이터 조회 (매치 종류, 등급 식별자)
피파의 2개의 메타데이터가 필요하니 '2개의 메서드를 가진' 서비스 클래스를 작성해 보자
FifaMetadataService, FifaMetadataServiceImpl(인터페이스, 구현체)
1. 경기 종류 리스트, 티어 종류 리스트를 모두 JSON에서 DTO로 변환하였다.
public interface FifaMetadataService {
List<MatchTypeDTO> getMatchTypeDTOList(); // 피파의 모든 경기 종류 리스트 가져오기
List<DivisionDTO> getDivisionDTOList(); // 피파의 모든 티어 종류 리스트 가져오기
}
@Service
@RequiredArgsConstructor // final 선언 필드 생성자 생성
@Slf4j
public class FifaMetadataServiceImpl implements FifaMetadataService{
RestTemplate restTemplate = new RestTemplate();
// 피파의 모든 경기 종류 리스트를 가져와 DTO 리스트로 반환
public List<MatchTypeDTO> getMatchTypeDTOList() {
String url = "https://static.api.nexon.co.kr/fifaonline4/latest/matchtype.json";
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
List<MatchTypeDTO> matchTypeDTOList = new ArrayList<>();
try {
JSONArray jsonArray = new JSONArray(responseEntity.getBody()); // 받아온 responseEntity의 body의 Json데이터 추출
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i); // JSON 배열의 i 번째 데이터 JSON 객체로 반환
// 경기 종류를 저장하는 DTO 생성 후 값 저장 (id, 경기 종류) > : {"matchtype":30,"desc":"리그 친선"}...
MatchTypeDTO matchTypeDTO = new MatchTypeDTO();
matchTypeDTO.setMatchType(jsonObject.getInt("matchtype"));
matchTypeDTO.setDesc(jsonObject.getString("desc"));
// 객체를 리스트에 추가
matchTypeDTOList.add(matchTypeDTO);
}
} catch (JSONException e) {
e.printStackTrace();
}
return matchTypeDTOList;
}
// 피파의 모든 티어 종류 리스트를 가져와 DTO 리스트로 반환
public List<DivisionDTO> getDivisionDTOList() {
String url = "https://static.api.nexon.co.kr/fifaonline4/latest/division.json";
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
List<DivisionDTO> divisionDTOList = new ArrayList<>();
try {
JSONArray jsonArray = new JSONArray(responseEntity.getBody()); // 받아온 responseEntity의 body의 Json데이터 추출
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i); // JSON 배열의 i 번째 데이터 JSON 객체로 반환
// 티어 정보 저장하는 DTO 생성 후 값 저장 (id, 티어 이름) > {"divisionName":"슈퍼챔피언스","divisionId":800}]...
DivisionDTO divisionDTO = new DivisionDTO();
divisionDTO.setDivisionId(jsonObject.getInt("divisionId"));
divisionDTO.setDivisionName(jsonObject.getString("divisionName"));
// 객체를 리스트에 추가
divisionDTOList.add(divisionDTO);
}
} catch (JSONException e) {
e.printStackTrace();
}
return divisionDTOList;
}
}
🧑🏻💻 3번) 유저의 데이터 식별 번호들과 메타 데이터와 매칭시켜 값을 추출
위에 FifaMetadataServiceImpl에서 받아온 피파의 메타 데이터들과
FifaUserServiceImpl에서 받은 유저의 데이터들을 서로 매칭시켜줄 기능을 작성한다.
FifaMetadataMatcherService, FifaMetadataMatcherServiceImpl(인터페이스, 구현체) 작성
/**
* @version 1.0
* @Author seodong-geun
* @since 2023/05/15
* 유저의 데이터와 피파의 메타데이터를 매치 하여
* 유저의 데이터가 어떤 데이터를 의미하는지 매치해주는 인터페이스 클래스
*/
public interface FifaMetadataMatcherService {
// 유저의 최고 티어가 기록된 경기 종류를 반환 ex) 공식경기, 감독모드
String getMatchTypeResult(int userMatchTypeId, List<MatchTypeDTO> matchTypeDTOList);
// 유저의 최고 티어를 반환 ex) 챌린지1, 슈퍼챔피언스
String getDivisionResult(int userDivisionId, List<DivisionDTO> divisionDTOList);
}
/**
* @version 1.0
* @Author seodong-geun
* @since 2023/05/15
* 유저의 데이터와 피파의 메타데이터를 매치 하여
* 유저의 데이터가 어떤 데이터를 의미하는지 매치해주는 구현 클래스
*/
@Service
@Log4j2
public class FifaMetadataMatcherServiceImpl implements FifaMetadataMatcherService {
// 유저의 최고티어 '경기종류'를 반환
public String getMatchTypeResult(int userMatchTypeId, List<MatchTypeDTO> fifaMatchTypeDTOList) {
// 경기 종류 DTO 목록에서 피파 메타데이터 경기 종류와 일치하는 값을 찾아서 매칭된 경기 종류 이름을 반환한다.
for (MatchTypeDTO matchTypeDTO : fifaMatchTypeDTOList) {
if (matchTypeDTO.getMatchType() == userMatchTypeId) {
return matchTypeDTO.getDesc(); // 만약
}
}
return null;
}
// 유저의 경기 종류별 '최고 티어'를 반환
public String getDivisionResult(int userDivisionId, List<DivisionDTO> fifaDivisionDTOList) {
// '유저 경기별 티어 DTO 목록'에서 '피파 메타데이터 티어 종류'와 일치하는 값을 찾아서 매칭된 티어 이름을 반환한다.
for (DivisionDTO divisionDTO : fifaDivisionDTOList) {
if (divisionDTO.getDivisionId() == userDivisionId) {
return divisionDTO.getDivisionName();
}
}
return null;
}
}
🧑🏻💻 서비스 코드 수정, 화면 코드 수정.
이제 서비스 구현체 코드를 다시 수정해 보자.
위에 작성했던 메서드들을 적절히 섞어 원하는 결과를 Controller에 전달할 수 있게 수정한다.
이후 컨트롤러에서 받아 > 화면에 전달한다.
<h1>유저정보</h1>
<p th:text="${nickNameUser.nickname} + ' 구단주님'"></p>
<p th:text="'레벨 : ' + ${nickNameUser.level}"></p>
<p th:text="'accessId : ' + ${accessIdUser.accessId}"></p>
<tbody>
<div th:each="match : ${userMatchHistory}">
<p th:text="${match.getMatchType()} + ' 최고 티어 :' + ${match.getDivision()}"></p>
<!-- 나머지 필드들도 출력 가능 -->
</div>
</tbody>
💻 결과 화면
이제 닉네임을 검색하면 [레벨, 닉네임, 공식경기, 감독모드 최고 티어]가 보인다!
다음 기능도 얼른 개발하러 가봐야 겠다 :)
[느낀 점은 따로 적어보겠다.!)