🏃🏻♂️🏃🏻♀️ 러너스하이 iOS Ver.릴리즈
- 진행기간 : 2020년 8월 24일 ~ 현재진행중
이전 리드미 보기
우리는 '함께' 뛸 때 더 많은 시너지를 만들어냅니다. 요즘 세대들은 러닝 크루에 소속되어 러닝을 즐기곤 하지만, Offline 러닝크루는 고정된 시간과 장소라는 한계점을 가지고 있습니다. 우리는 같이 달리고 싶지만, 달릴 수 없는 순간들이 존재한다는 점에 집중하고자 합니다. 우리의 서비스를 통해 시공간의 제약없이 다양한 사람들과 함께 달림으로써 건강한 라이프 스타일을 만들어나가길 바랍니다.
: 기존 러닝 어플리케이션과의 확실한 차별화 요소를 적용했습니다.
: 어떤 단체에 소속되지 않아도, 굳이 친구와 약속을 잡고 만나지 않아도, 사용자는 언제 어디서든 나와 함께 뛸 상대를 찾아 같이 러닝을 즐길 수 있습니다.
: 특정 목표를 달성하면 개성있는 여러 가지 뱃지를 획득할 수 있음과 동시에 다양한 러너 랭킹을 통해 사용자의 즐거움을 도모하고자 합니다. 또, 누구나 사용하기 쉬운 UX 요소는 즐거움을 배로 향상시켜 줄거에요.
=> 발표영상 보기
| 화면 이름 | 기능 | 구현 | 담당자 |
|---|---|---|---|
| 회원 가입 | 회원 가입 제거 | 🔵 | 김민희 |
| 스플래쉬화면 | uuid로 계정 생성 | 🔵 | 김민희 |
| 매칭화면 | 소켓 통신 제거 | 🔵 | 김민희 |
| 매칭요청화면 | http-post 방식으로 매칭 요청 | 🔵 | 김민희 |
| 매칭성공화면 | http-get 방식으로 상대방 정보 받아오기 | 🔵 | 김민희 |
| 러닝화면 | 매칭된 사용자와 순위 비교 | 김민희 | |
| 러닝화면 | http-put 방식으로 순위 변경 알림 | 김민희 | |
| 러닝기록상세보기화면 | http방식으로 뛰었던 정보 받아오기 | 최영재 | |
| 레코드탭 | 뱃지보기 제거 | 🔵 | 최영재 |
: Tab Bar을 이용해 각 스토리보드를 이어주며 이동 가능
🥳 앱을 처음 구동할 때 뜨는 화면. UUID 체크인도 여기서 발생한다.
🥳 Main 화면. 일러스트롤 포함하며, RUN NOW 버튼 클릭시 주요 기능은 매칭 서비스가 시작된다. 원하는 매칭 러너의 조건을 설정하고 매칭이 되면 상대방 프로필을 확인한 후, 러닝이 시작된다.

🥳 매칭이 되면 상대방 프로필을 확인한 후, 러닝이 시작된다. 실시간으로 자신의 속도(km), 페이스(pace), 남은 시간이 표시되고 현재 자신이 뛰고있는 위치가 지도(네이버)를 통해 표시된다.
🤓 함께 뛰는 러너와의 실시간 순위를 보여줘 러닝 욕구를 더욱 자극시킨다.
: 자신이 지금까지 쌓아온 러닝 기록을 확인할 수 있다.
: 현재 이 어플에서 '이달의 러너', '명예의 전당', '졌.잘.싸' 로 나눠진 3개의 랭킹 순위를 확인할 수 있다.
: 자신의 기본 정보(프로필 사진, 닉네임, 레벨, 전적)을 확인할 수 있고 모아둔 뱃지를 간략히 확인할 수 있다.
-
UUID 체크인
: UUID는 Universally Unique IDentifier의 약어로 범용 고유 식별자이다. uuid의 포맷은 총 36개의 문자를 8–4–4–4–12로 구분한 형태이다. 회원가입을 제거한 이유는 이 전에는 회원가입을 꼭 해야지만 기능을 누릴 수 있었는데 그렇게 된다면 많은 초기 사용자가 유입되지 못하는 이유가 될 수 있다. 이런 이유로 어플을 둘러볼 수 있게 하기 위해서 uuid를 사용해 회원가입 대신 사용하고 있다.CheckInUUID(uuid: UIDevice.current.identifierForVendor?.uuidString ?? "")
struct UuidDetail: Codable { let accessToken, nickname: String let gender, image, level: Int let badge: String let win, lose: Int }
: UIDevice.current.identifierForVendor?.uuidString을 통해 기기 고유의 uuid값을 추출해온다. 그리고 그 값을 서버에 넘기면 서버는 이 기기가 처음 어플에 들어온 사용자인지, 혹은 이미 방문했던 사용자인지 구분한다. 만약 처음 어플에 들어온 사용자라면 임시 계정을 발급해주고 두번째 이상 방문이라면 그 전에 발급받았던 임시 계정을 보내준다. 어플을 사용하면서 제일 필요한 토큰과 마이페이지에 필요한 정보들을 http통신을 통해 받는다.
-
CoreData
: CoreData는 프레임 워크이다. 그 중 Persistence 기능은 관계형 데이터베이스인 SQLite을 통해 지원되기 때문에 이 기능을 이용해 디바이스에 permanent data(영구적인 데이터)를 저장할 수 있다.
@nonobjc public class func fetchRequest() -> NSFetchRequest<Information> { return NSFetchRequest<Information>(entityName: "Information") } @NSManaged public var accessToken: String? @NSManaged public var badge: String? @NSManaged public var gender: Int64 @NSManaged public var level: Int64 @NSManaged public var image: Int64 @NSManaged public var lose: Int64 @NSManaged public var nickname: String? @NSManaged public var win: Int64
: 위의 uuid 체크인에서 받아온 정보를 CoreData에 저장하고자 한다. 그 이유는 사용자의 정보는 매칭 할 때, 매칭 중, 매칭 후의 화면에서도 쓰이고 마이페이지 화면에서도 쓰이는 등 자주 사용되는 정보이고 특히 토큰값은 서버에 전달할 일이 많기 때문에 UserDefaults보다 CoreData를 사용해서 저장하는 것이 접근성이 더 좋다고 판단했다.
func saveUser(accessToken: String, nickname: String, gender: Int64, level: Int64, image: Int64, badge: String, win: Int64, lose: Int64, onSuccess: @escaping ((Bool) -> Void)) { if let context = context, let entity: NSEntityDescription = NSEntityDescription.entity(forEntityName: infoModel, in: context) { if let user: Information = NSManagedObject(entity: entity, insertInto: context) as? Information { user.accessToken = accessToken user.nickname = nickname user.level = level user.gender = gender user.image = image user.badge = badge user.win = win user.lose = lose contextSave { success in onSuccess(success) } } } }
: 위에서 생성해준 Information 구조와 같게 값을 저장하는 함수를 만들어준다.
fileprivate func saveUserInfo(_ accessToken: String, nickname: String, gender: Int64, level: Int64, image: Int64, badge: String, win: Int64, lose: Int64) { CoreDataManager.shared.saveUser(accessToken: accessToken, nickname: nickname, gender: gender, level: level, image: image, badge: badge, win: win, lose: lose) { onSuccess in print("saved = \(onSuccess)") } }
: 서버에 연결해 값을 받아오는데 성공하면 이 값들을 사용자의 정보를 저장하는 CoreData 함수에 전달한다. 그리고 앱을 새로 접속할 때 마다 새로운 토큰으로 변경되기 때문에 앱을 새로 시작할 때는 information에 data가 저장되어 있는지 확인한 후, 있다면 삭제하고 새로 받아온 값을 저장해주는 것이 중요하다.
- 김민희 Repo : 러너스하이 iOS 리드개발자, MainTab 구현 및 러닝 구현 담당
- 최영재 Repo : 러너스하이 iOS 서브개발자, RankTab / RecordTab / MyPabeTab / SignTab 담당
: IT 창업 동아리 26th ‘SOPT’ APPJAM 대상 수상, 현재 앱스토어 출시 준비 중.









