Api๋ฅผ ๋ง๋ ๊ณผ์ ์ ๋ํ ๊ธ์
๋๋ค.
๋ฌธ์ ๊ฐ ๋ณด์ธ๋ค๋ฉด ๋ฐ๋ก๋ฐ๋ก ๋ฆฌ๋ทฐ ๋ถํ๋๋ฆฝ๋๋ค!
์ผ๋จ Api๋ฅผ ๋ง๋ค๊ธฐ ์ ์ ํด๋น Api์ ๋ํ ๋์์ธ์ ๊ฐ๋จํ๊ฒ ๋ง๋ค์๋ค.
๋์์ธ์ ์๊ฐํ์ง ์๊ณ ๋ง๋๋ ๋ด๊ฐ ๋ง๋ค๊ณ ์ ํ๋ Api๊ฐ ์ด๋ป๊ฒ ์ฌ์ฉ๋๋์ง ๊ฐ์ด ์์๊ธฐ ๋๋ฌธ์ด๋ค.
<์น๋ฆฌ๊ฐ ๋ง์ ๋ถ๋ถ์ ์๋ผ๋ธ๊ฒ์ด ์๋๋ผ ํ์ ์ค๋ ฅ์ด ์ข์์ ์น๋ฆฌ๊ฐ ๋ง์๊ฒ๋๋ค>
์ผ๋จ ์ํ์ฌ๋ฅผ ๊ฒ์ ํ๋ฉด ๋ฌด์กฐ๊ฑด ์ ์ ๋ฆฌ์คํธ ๋ํ ๊ฐ์ ธ์ค๋๋ก ํ์๊ณ ์๊ฐ ํ๊ธฐ ๋๋ฌธ์
์ํ์ฌ ๊ฐ์ฒด๊ฐ ์ ์ ๋ฆฌ์คํ ๊ฐ์ ธ์ผ ํ๋ค๊ณ ์๊ฐํ๋ค.
์ผ๋จ ํ ์คํธ ์ฝ๋๋ฅผ ์์ฑํ๊ณ
@SpringBootTest
class SummonerServiceTest {
@Autowired
SummonerService summonerService;
@Test
void save() {
String name = "ํฐ๊ณ ๋ชจ๋ถ";
Summoner summoner = summonerService.getSummoner(name);
assertThat(summoner.getSummonerName()).isEqualTo("ํฐ๊ณ ๋ชจ๋ถ");
}
}
์ํ์ฌ ์ ๋ณด์ ์ํ์ฌ ์ ์ Entity๋ฅผ ๋ง๋ค์๋ค.
@Entity
@Data
public class Summoner {
@Id @GeneratedValue
@Column(name = "summoner_id")
private long id;
private String summonerName;
private String puuid;
private int profileIcon;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "summoner_id")
private List<MatchReference> matchReferences;
public Summoner(String summonerName, String puuid, int profileIcon, List<MatchReference> matchReferences) {
this.summonerName = summonerName;
this.puuid = puuid;
this.profileIcon = profileIcon;
this.matchReferences = matchReferences;
}
public Summoner() {
}
public static Summoner of(SummonerDto summonerDto, List<MatchReference> matchReferences) {
return new Summoner(summonerDto.getName(), summonerDto.getPuuid(), summonerDto.getProfileIconId(), matchReferences);
}
}
@Entity
public class MatchReference {
@Id @GeneratedValue
@Column(name = "match_id")
private long matchId;
private long gameId;
private String role;
private int championId;
private String lane;
private Date timestamp;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "summoner_id", insertable = false, updatable = false)
private Summoner summoner;
public MatchReference(long gameId, String role, int championId, String lane) {
this.gameId = gameId;
this.role = role;
this.championId = championId;
this.lane = lane;
}
public MatchReference() {
}
public static List<MatchReference> of(MatchListDto matchListDto) {
List<MatchReferenceDto> matchReferenceDtos = matchListDto.getMatches();
return matchReferenceDtos.stream()
.map(e -> new MatchReference(e.getGameId(), e.getRole(), e.getChampion(), e.getLane()))
.collect(Collectors.toList());
}
}
์ํ์ฌ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ Entity์ ์ํ์ฌ ์ ์ ๋ฆฌ์คํธ์ ๋ํ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ Entity๋ฅผ ๋ง๋ค์๋ค.
์๋ฐ ORM ํ์ค JPA ํ๋ก๊ทธ๋๋ฐ ์ฑ
์์ ์ผ๋๋ค ์๋ฐฉํฅ Mapping์ ๋ณด๊ณ ์ค์ ํ๋๋ฐ.
์ฌ์ค ์๊ฐํด๋ณด๋ฉด ์ผ๋๋ค ๋จ๋ฐฉํฅ Mapping์ด ๋ง๋ค๊ณ ์๊ฐ์ด ๋ค์์ง๋ง ์ผ๋๋ค ๋จ๋ฐฉํฅ Mapping๋ณด๋จ ๋ค๋์ผ ์๋ฐฉํฅMapping์ ํ๋ผ๊ณ ์ ํ ์์๋ค.
๊ทธ๋ฐ๋ฐ ํ๋ช
์ ์ํ์ฌ ๊ฐ ์ฌ๋ฌ ์ ์ ๋ฆฌ์คํธ๋ฅผ ๊ฐ์ง๊ณ ์๊ณ ์ฃผ์ฒด๊ฐ ์ํ์ฌ ์ด๊ธฐ ๋๋ฌธ์ ์ผ๋๋ค ๊ฐ ๋ง๋ค๊ณ ์๊ฐํ๊ณ , ์ผ๋๋ค ๋จ๋ฐฉํฅ์ ์ถ์ฒํ์ง ์์ผ๋ ์๋ฐฉํฅ์ผ๋ก ์ผ๋จ ์ค์ ํด๋๊ณ , JPA๋ฅผ ์ข ๋ ์์๋ณด๊ณ ์์ ํด์ผ ๊ฒ ๋ค๊ณ ์๊ฐ ํ๋ค.
Controller, Service, Repository๋ฅผ ๋ง๋ค์๋ค.
@RestController
public class SummonerController {
public final RiotApi riotApi;
public final SummonerService summonerService;
public SummonerController(RiotApi riotApi, SummonerService summonerService) {
this.riotApi = riotApi;
this.summonerService = summonerService;
}
@GetMapping("/summoners/{summonerName}")
public Summoner getSummoner(@PathVariable String summonerName) {
return summonerService.getSummoner(summonerName);
}
}
@Service
public class SummonerService {
private final RiotApi riotApi;
private final SummonerRepository summonerRepository;
public SummonerService(RiotApi riotApi, SummonerRepository summonerRepository) {
this.riotApi = riotApi;
this.summonerRepository = summonerRepository;
}
public Summoner getSummoner(String summonerName) {
if (summonerRepository.existsBySummonerName(summonerName)) {
return summonerRepository.findBySummonerName(summonerName);
}
SummonerDto summonerDto = riotApi.getSummoner(summonerName);
MatchListDto matchListDto = riotApi.getMatches(summonerDto.getAccountId());
return summonerRepository.save(Summoner.of(summonerDto, MatchReference.of(matchListDto)));
}
}
@Repository
public interface SummonerRepository extends JpaRepository<Summoner, Long> {
boolean existsBySummonerName(String summonerName);
Summoner findBySummonerName(String summonerName);
}
๊ทธ๋ฆฌ๊ณ DB์ ์ ์ ์ฅ ๋๋ ๊ฒ์ ํ์ธ ํ๋ค.
๊ฐ๋จํ Api์์
์ด์์ง๋ง ์์ฌ์ด๊ฒ์ ๋ง์๋ค.
์ ๋ฆฌ ํด๋ณด๋ฉด
- Jpa์ ๋ํด์ ์๋ชจ๋ฅธ๋ค. (๊ณต๋ถํ ๊ฑด ๋ง์๋ฐ ๋๋ฌด ์๊ฐ ์์ด ์ง๋๊ตฌ๋..)
- Rate Limit๋ฅผ ํด๊ฒฐ ํ์ง ๋ชปํ๋ค.
์ด ์ธ ๋ถ๋ถ์ด ์์ฌ์ ๋ค.
ํผ์ ํ๋๊ฒ์ด ์ฝ์ง ์๋ค๋ ๊ฒ์ ์๊ณ ์์์ง๋ง.
์ด๋ ๊ฒ ๊น์ง ๋นํจ์จ์ ์ผ๊ฑฐ๋ผ๊ณ ์๊ฐํ์ง ๋ชปํ๋ค.
๋ด ์์ ์๊ฒ ์ข ์์ฌ์ด๊ฒ ๋ง์๋ค.
์ทจ์ ์ ์ฑ๊ณต ํ์ง๋ง ์ทจ์ ์ ์ฑ๊ณตํ๋ ๋์ ์ถฉ๋ถํ ๊น๊ฒ ์๊ฐํด๋ณด๊ณ ๋๋ฆ ๊ฒฌ๊ณ ํ๊ฒ ์ค๊ณ ํ ์ ์์์ ํ ๋ฐ ๊ทธ๋ฌ์ง ๋ชปํ๊ฑด ์์ฌ์ด๊ฒ ๊ฐ๋ค.