1. 개요
Tripot 프로젝트는 모바일 서비스이다. 어플을 운영하다 보면 버그가 생길 수 있다. 만약 치명적인 버그라면? 이를 수정했는데 업데이트 없이 그대로 사용하는 유저가 있다면? 업데이트를 한 사용자와 하지 않은 사용자는 UX적으로 큰 차이를 경험하게 될 것이다. 이를 방지하기 위해 버전을 서버에 저장하고, 사용자의 버전에 따라 업데이트를 권장하거나 강제하는 기능을 만들고자 한다.
2. ERD
ERD는 다음과 같다. 개인적으로 처음 구현해보는 기능이라 설계에서 애를 좀 먹었다. 필드를 하나씩 살펴보자.
- version_id: 해당 정보의 PK이다.
- version: 앱 버전을 기술한다. 1.0.1, 1.0.2와 같이 앱 버전이 들어갈 수 있다. 원활한 버전 비교 및 저장을 위해 문자열로 저장했다.(1.2.10 등)
- force_update: 해당 버전의 하위 버전이 위험하다면 true를 저장한다. 이 때는 버전 비교 시 하위 버전일 경우 업데이트를 강제하기로 한다.
- platform: enum 필드이다. 현재는 ios만으로 운영하고 있지만 추후 안드로이드 서비스를 예정함에 따라 플랫폼 별로 버전을 따로 관리하고자 추가하였다.
이를 기반으로 도메인을 다음과 같이 작성하였다.
@Entity
@Getter
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
public class Version extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "version_id")
private Long id;
@Column(length = 15)
private String version;
//true일 경우 해당 하위 버전은 해당 버전까지의 강제 업데이트를 요구함
private Boolean forceUpdate;
@Enumerated(value = EnumType.STRING)
private Platform platform;
}
3. 기능
3-1. VersionService
기능 자체는 매우 간단하므로 묶어서 작성하였다.
@Service
@RequiredArgsConstructor
@Slf4j
@Transactional(readOnly = true)
public class VersionService {
private final VersionRepository versionRepository;
@Transactional
public void createVersion(VersionDto versionDto, Platform platform) {
Version version = Version.builder()
.platform(platform)
.version(versionDto.version())
.forceUpdate(versionDto.forceUpdate())
.build();
versionRepository.save(version);
}
public VersionCheckResponseDto checkVersion(Platform platform, String version) {
Version latestVersion = versionRepository.findFirstByPlatformOrderByCreatedDateDesc(platform)
.orElseThrow(() -> new CustomException(StatusCode.VERSION_NOT_FOUND));
boolean forceUpdate = false;
boolean requireUpdate = false;
if (version.compareTo(latestVersion.getVersion()) < 0) {
requireUpdate = true;
if (latestVersion.getForceUpdate()) {
forceUpdate = true;
}
}
return VersionCheckResponseDto.builder()
.requireUpdate(requireUpdate)
.forceUpdate(forceUpdate)
.build();
}
}
- createVersion: 간단하다. 컨트롤러 계층에서 넘어온 버전 정보, 강제 여부, 플랫폼을 받아 이를 DB에 저장한다.
- checkVersion: 사용자로부터 사용 플랫폼과 버전 정보를 받아온다. DB에서는 해당 플랫폼에 알맞는 가장 최근에 저장한, 즉 최신 버전을 받아온다. 이 둘을 비교하여 사용자가 구버전일 경우, 최신 버전이 강제해야 할 경우 강제 여부를 true, 그렇지 않다면 false를 반환하여 리턴한다.
3-2. VersionController
@RestController
@RequiredArgsConstructor
@Slf4j
public class VersionController {
private final VersionService versionService;
@Secured("ADMIN")
@PostMapping("/api/v1/versions/{platform}")
public ResponseEntity<CommonResponse<Object>> createVersion(@RequestBody VersionDto versionDto, @PathVariable("platform") String platform) {
versionService.createVersion(versionDto, Platform.valueOf(platform.toUpperCase()));
return ResponseEntity.status(StatusCode.VERSION_CREATE_SUCCESS.getHttpCode()).body(CommonResponse.success(StatusCode.VERSION_CREATE_SUCCESS, null));
}
@GetMapping("/api/v1/versions/{platform}/check")
public ResponseEntity<CommonResponse<VersionCheckResponseDto>> checkVersion(@RequestParam("version") String version, @PathVariable("platform") String platform) {
return ResponseEntity.status(StatusCode.VERSION_CHECK_SUCCESS.getHttpCode()).body(CommonResponse.success(StatusCode.VERSION_CHECK_SUCCESS, versionService.checkVersion(Platform.valueOf(platform.toUpperCase()), version)));
}
}
컨트롤러 역시 간단히 작성했다. 버전을 저장하는 것은 관리자만 가능해야 하므로 Secured로 권한을 제한했다.
'Proj > Tripot' 카테고리의 다른 글
MySQL 백업하기 (0) | 2025.03.05 |
---|---|
Trouble Shooting - nginx 용량 늘리기(feat. 스토리 등록 오류) (0) | 2025.03.04 |
소셜 로그인 - 애플 identity_token에서 사용자 정보 가져오기 (0) | 2025.02.14 |
Trouble Shooting - Spring Security 프로젝트에 비로그인으로 접속 시 (0) | 2025.02.11 |
Trouble Shooting - docker compose vs docker-compose (0) | 2025.02.10 |