[만보기 어플 만들기] Kotlin으로 만보기 앱 개발하는 방법

개발 테크
2024. 07. 18
조회수
4,160

만보기-어플

고객이 어플을 계속해서 사용하도록 어플에 여러 기능들을 추가해 어플 사용량을 늘리고 어플 친숙도를  높여 충성 고객을 확보하도록 목적을 가진 어플이 있습니다. 바로 슈퍼 앱입니다. 

슈퍼 앱, 궁극의 올인원 서비스로 고객을 확보하세요!

슈퍼 앱은 하나의 어플의 다수의 기능을 탑재함으로써 마치 복합 쇼핑몰에 들어온 것처럼 고객을 사로잡는 ‘락인(Lock in)’ 기능을 가지고 있는데요. 이 기능을 강화하기 위해, 네이버, 카카오 등 빅 테크 기업부터 금융 IT 기업까지 ‘만보기’ 어플을 활용하고 있습니다.

어플 친숙도와 사용도를 높여 충성고객 확보를 도와주는 만보기 어플, 대한민국 No.1 IT 인재 매칭 플랫폼 이랜서에서 안드로이드 대표 언어 Kotlin으로 개발하는 방법을 알려드리겠습니다.



 

만보기 기능, 빅 테크 기업들은 이래서 사용합니다.

만보기-앱

사람들은 자신이 사용하기 익숙한 어플을 찾게 됩니다. 아이폰을 사용한 사람은 계속 아이폰을 찾게 되고 갤럭시를 사용한 사람은 계속 갤럭시를 찾는 것처럼요. 그래서 모바일 시장에선 소비자가 사용하기에 친숙한 어플을 만들기 위해 여러 가지 기능들을 추가하는데요. 대표적인 것이 바로 ‘만보기 기능’입니다. 

빅 테크나 금융 IT 기업들은 어플에 만보기 기능을 추가해 고객이 계속해서 사용하도록 유도하고 있습니다. 만보기 어플은 건강과 관련된 헬스케어에 대한 데이터도 수집할 수 있어, 어플 친숙도와 미래 성장 산업을 위한 데이터두마리 토끼를 모두 잡을 수 있게 됩니다.



 

고객을 사로잡는 만보기 어플 만드는 방법

이로 인해 네이버, 카카오, 토스 등 잘나가는 테크 기업과 금융 IT 기업들은 ‘만보기 어플’ 추가해 충성고객을 확보하고 있는데요. 이랜서에서 Kotlin을 활용하여 만보기 어플 만드는 방법을 알려드리겠습니다. 만보기 어플 개발 방법이 궁금한 분들은 끝까지 집중하세요.

 

안드로이드에서 어플 개발을 위해 윈도우 노트북에서 IDE는 안드로이드 스튜디오, 언어는 코틀린을 사용했습니다.



 

만보기 어플 레이아웃 만들기

만보기 어플을 만들기 위해서, 먼저 레이아웃을 만들어야 합니다. 

이랜서에서는 IT 전문가의 체력 향상과 개인 성장을 돕는 달리기 커뮤니티 ‘ERC(Elancer Run Club)’를 주최해 IT 전문가의 자기 계발(커리어 개발)을 돕고 있는데요. 이랜서 런클럽 ERC 로고를 활용해 만보기 어플 레이아웃을 만들어 보겠습니다.   

만보기-앱-테크

레이아웃은 Jetpack Compose를 사용하여 만들었습니다. Jetpack Composet는 UI 개발을 간소화하기 위해 설계된 최신 툴킷으로 동적인 UI를 구현하는데 장점이 있습니다.

override fun onCreate(savedInstanceState: Bundle?) {
   super.onCreate(savedInstanceState)

   setContent {
 
       SensorExamTheme {
           Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
               StepCounterUI()
           }
       }
   }
}

 

 

@Composable
fun StepCounterUI() {
   Box(
       modifier = Modifier
           .fillMaxSize()
           .background(Color.White),
       contentAlignment = Alignment.TopCenter
   ) {
       Column(
           horizontalAlignment = Alignment.CenterHorizontally,
           verticalArrangement = Arrangement.Top
       ) {
           Box(
               modifier = Modifier
                   .height(30.dp)
                   .fillMaxWidth()
                   .background(Color(0xFFFF6F00))
           )
           Box(
               modifier = Modifier
                   .height(15.dp)
                   .fillMaxWidth()
                   .background(Color(0xFF595959))
           )

           Row(
               modifier = Modifier
                   .fillMaxWidth()
                   .padding(top = 30.dp),
               verticalAlignment = Alignment.CenterVertically,
               horizontalArrangement = Arrangement.Center
           ) {
               Text(
                   text = "이랜서",
                   fontSize = 35.sp,
                   fontWeight = FontWeight.Bold,
                   fontFamily = customFontFamily,
                   color = Color.Black
               )
               Spacer(modifier = Modifier.width(10.dp)) // Add some space between the texts
               Text(
                   text = "LEARN & RUN",
                   fontSize = 35.sp,
                   fontWeight = FontWeight.Bold,
                   fontFamily = customFontFamily,
                   color = Color(0xFFFF6F00)
               )
           }

           Text(
               text = "'배우면서 달린다. 달리면서 배운다'",
               fontSize = 24.sp,
               fontFamily = customFontFamily,
               color = Color(0xFF797979)
           )

           // Image
           val image: Painter = painterResource(id = R.drawable.logo)
           Image(
               painter = image,
               contentDescription = "Logo",
               contentScale = ContentScale.FillWidth,
               modifier = Modifier
                   .fillMaxWidth()
                   .padding(start = 16.dp, end = 16.dp)
           )

           Row(
               modifier = Modifier
                   .fillMaxWidth()
                   .padding(top = 16.dp, start = 16.dp, end = 16.dp, bottom = 8.dp),
               verticalAlignment = Alignment.CenterVertically,
               horizontalArrangement = Arrangement.Center
           ) {
               Text(
                   text = stepValue.value,
                   Modifier.width(220.dp),
                   fontSize = 60.sp,
                   textAlign = TextAlign.End,
                   fontWeight = FontWeight.Bold,
                   fontFamily = customFontFamily,
                   color = Color(0xFFFF6F00)
               )

               Spacer(modifier = Modifier.width(20.dp)) // Add some space between the texts
               Text(
                   text = "걸음",
                   fontSize = 40.sp,
                   fontWeight = FontWeight.Bold,
                   fontFamily = customFontFamily,
               )
               Spacer(modifier = Modifier.width(10.dp))

           }

           Box(
               modifier = Modifier
                   .height(3.dp)
                   .padding(horizontal = 35.dp)
                   .fillMaxSize()
                   .background(Color(0xFF000000))

           )

           Row(
               modifier = Modifier
                   .fillMaxWidth()
                   .padding(horizontal = 35.dp),
               verticalAlignment = Alignment.CenterVertically,
           ) {
               Text(
                   text = "총 7km",
                   fontSize = 25.sp,
                   fontFamily = customFontFamily,
                   color = Color.Black
               )
               Spacer(modifier = Modifier.width(5.dp)) // Add some space between the texts
               Text(
                   text = "걸음",
                   fontSize = 25.sp,
                   fontFamily = customFontFamily,
                   color = Color(0xFFcacaca)
               )
               Spacer(modifier = Modifier.weight(1f))
               Box(
                   modifier = Modifier
                       .clickable(onClick = {
                           _stepValue.value = "0"
                       })
                       .padding(8.dp)
                       .width(100.dp)
                       .height(50.dp)
                       .background(Color(0xFFFF6F00), shape = RoundedCornerShape(8.dp)),
                   contentAlignment = Alignment.Center
               ) {
                   // Additional content goes here
                   Text(
                       text = "Reset",
                       fontSize = 30.sp,
                       fontWeight = FontWeight.Bold,
                       fontFamily = customFontFamily,
                       color = Color(0xFFFFFFFF),
                   )
               }
           }

           Spacer(modifier = Modifier.height(20.dp))

           // Placeholder for additional content
           Box(
               modifier = Modifier
                   .padding(16.dp)
                   .fillMaxWidth()
                   .height(100.dp)
                   .background(Color(0xFFcacaca), shape = RoundedCornerShape(8.dp))

           ) {
               // Additional content goes here
           }

           Spacer(modifier = Modifier.weight(1f))

           Box(
               modifier = Modifier
                   .height(15.dp)
                   .fillMaxWidth()
                   .background(Color(0xFF595959))
           )

           Box(
               modifier = Modifier
                   .height(30.dp)
                   .fillMaxWidth()
                   .background(Color(0xFFFF6F00))
           )


       }
   }
}

폰트‘원스토어  mobile pop 서체’를 사용했습니다. 폰트를 사용하기 위해 customFontFamily를 지정했습니다. Jetpack Compose가 익숙하지 않은 분은 기존처럼 layout 파일을 사용하여 구현하셔도 됩니다.

 

만보기 어플 기능 구현하기 

만보기 어플을 만들기 위해 레이아웃을 설정했으니, 이제 만보기 기능을 추가해보겠습니다. 사용자의 걷는 동작을 감지하기 위해 SensorManager 클래스를 사용했습니다.

 

퍼미션(Permission) 추가

SensorManager를 사용하려면 퍼미션을 추가해야 합니다. 퍼미션이란 특정 파일이나 디렉터리에 읽기, 쓰기, 삭제 등의 권한을 설정해 놓은 것으로 다중 사용자 운영체제에서 파일에 대한 접근 권한과 보호를 위해 반드시 필요합니다. 다중이 사용하는 만보기 어플을 만들기 위해선 반드시 퍼미션을 추가해야 합니다. 

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

   xmlns:tools="http://schemas.android.com/tools">

 

   <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" />

 

   <application
}

 


 

AndroidManifest 파일을 열고 ACTIVITY_RECOGNITION 퍼미션을 선언하세요.


 

센서 셋업

private var sensorManager: SensorManager? = null

 

 

override fun onCreate(savedInstanceState: Bundle?) {

   super.onCreate(savedInstanceState)

 

   sensorManager = getSystemService(SensorManager::class.java)

 

override fun onResume() {

   super.onResume()

 

   val sensor = sensorManager?.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)

 

}

옵션으로 넘기는 TYPE_STEP_COUNTER는 리턴 값이 무조건 1이고 이 종료되면 다시 0부터 시작합니다. TYPE_STEP_SCOUNTER를 지정하면 종료와 관계없이 계속 기존의 값을 가지고 있다가 1씩 증가한 값을 리턴합니다.


 

리셋 버튼 구현 

만보기의 순수 기능을 구현하기 위해 Reset 버튼을 추가했습니다. 기록을 측정하는 기록 장치를 보면 Reset 버튼이 있는데요. 걸음수를 초기화 할 수 있게 Reset 버튼을 누르면 걸음 수가 초기화되는 기능을 추가해 보겠습니다.

Box(

   modifier = Modifier

       .clickable(onClick = {

           _stepValue.value "0"

       })

       .padding(8.dp)

       .width(100.dp)

       .height(50.dp)

       .background(Color(0xFFFF6F00), shape = RoundedCornerShape(8.dp)),

   contentAlignment = Alignment.Center

) {

   // Additional content goes here

   Text(

       text = "Reset",

       fontSize = 30.sp,

       fontWeight = FontWeight.Bold,

       fontFamily = customFontFamily,

       color = Color(0xFFFFFFFF),

   )

}


 

센서 딜레이 세팅

센서 딜레이 세팅은 센서를 통해 데이터를 가져오는 속도를 조절하는 것입니다. 너무 빠른 속도로 데이터를 가져오게 될 경우 베터리나 시스템 자원이 낭비할 수 있어, 적절한 속도로 설정하는 것이 중요합니다. 

만보기 어플의 경우에는 SENSOR_DELAY_UI를 사용하면 적당하게 조절할 수 있습니다.

override fun onResume() {

   super.onResume()

   isRunning true

   val sensor = sensorManager?.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)

 

   sensor?.let {

       sensorManager?.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI)

   }

}

}

센서 속도를 설정합니다. 빠른 속도 순서는 SENSOR_DELAY_FASTEST, SENSOR_DELAY_GAME, SENSOR_DELAY_UI, SENSOR_DELAY_NORMAL입니다. 



 

메인 기능

이제 센서로 데이터를 받으면 화면에 표시하는 메인 기능을 구현하겠습니다. 이 기능은 만보기 어플의 핵심으로 센서를 통해 받은 데이터를 실시간으로 화면에 표시하는 수 역할을 합니다.

class MainActivity : ComponentActivity(), SensorEventListener {

 

override fun onSensorChanged(event: SensorEvent?) {

   if (event != null) {

       val isIncrementStep = abs(event.values[0].toInt() - prevStep)

       prevStep event.values?.get(0)?.toInt()!!

       log("abs(event.values[0].toInt() - totalStep): $isIncrementStep :: ${isIncrementStep == 1}")

 

       if (isRunning && isIncrementStep == 1) {

           _stepValue.value = (++stepCount).toString()

       }

   }

}

 

override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}

SensorEventListener를 MainActivity에 연동한 다음 onSensorChanged, onAccuracyChanged 메소드를 구현합니다.

onSensorChanged: 실제 센서의 작동과 관련된 함수입니다. 센서가 동작을 감지하면  onSensorChanged로 값이 넘어옵니다.

onAccuracyChanged: 센서의 정확도가 변경되었을 때 호출됩니다. 이 함수는 필요한 경우 구현하세요.



 

만보기 어플 기능을 추가한 전체 코드 

만보기 어플 구현을 위해 전체 코드를 보여드리겠습니다. 아래 코드대로 입력만 해도 만보기 기능을 구현할 수 있습니다.
 

package com.nokhyun.sensorexam

 

import android.Manifest

import android.content.pm.PackageManager

import android.hardware.Sensor

import android.hardware.SensorEvent

import android.hardware.SensorEventListener

import android.hardware.SensorManager

import android.os.Build

import android.os.Bundle

import android.util.Log

import androidx.activity.ComponentActivity

import androidx.activity.compose.setContent

import androidx.compose.foundation.Image

import androidx.compose.foundation.background

import androidx.compose.foundation.clickable

import androidx.compose.foundation.layout.Arrangement

import androidx.compose.foundation.layout.Box

import androidx.compose.foundation.layout.Column

import androidx.compose.foundation.layout.Row

import androidx.compose.foundation.layout.Spacer

import androidx.compose.foundation.layout.fillMaxSize

import androidx.compose.foundation.layout.fillMaxWidth

import androidx.compose.foundation.layout.height

import androidx.compose.foundation.layout.padding

import androidx.compose.foundation.layout.width

import androidx.compose.foundation.shape.RoundedCornerShape

import androidx.compose.material.Button

import androidx.compose.material.ButtonDefaults

import androidx.compose.material.MaterialTheme

import androidx.compose.material.Surface

import androidx.compose.material.Text

import androidx.compose.material.Typography

import androidx.compose.runtime.Composable

import androidx.compose.runtime.MutableState

import androidx.compose.runtime.State

import androidx.compose.runtime.getValue

import androidx.compose.runtime.mutableStateOf

import androidx.compose.runtime.remember

import androidx.compose.runtime.setValue

import androidx.compose.ui.Alignment

import androidx.compose.ui.Modifier

import androidx.compose.ui.graphics.Color

import androidx.compose.ui.graphics.painter.Painter

import androidx.compose.ui.layout.ContentScale

import androidx.compose.ui.res.painterResource

import androidx.compose.ui.semantics.Role.Companion.Image

import androidx.compose.ui.text.TextStyle

import androidx.compose.ui.text.font.Font

import androidx.compose.ui.text.font.FontFamily

import androidx.compose.ui.text.font.FontWeight

import androidx.compose.ui.text.style.TextAlign

import androidx.compose.ui.unit.dp

import androidx.compose.ui.unit.sp

import androidx.core.content.ContextCompat

import com.nokhyun.sensorexam.ui.theme.SensorExamTheme

import kotlin.math.abs

 

 

class MainActivity : ComponentActivity(), SensorEventListener {

 

   private var sensorManager: SensorManager? = null

   private var isRunning false

   private var prevStep 0

   private var stepCount 0

 

   private var _stepValue: MutableState<String> = mutableStateOf("0")

   var stepValue: State<String> = _stepValue

 

   override fun onCreate(savedInstanceState: Bundle?) {

       super.onCreate(savedInstanceState)

 

       if (ContextCompat.checkSelfPermission(

               this,

               Manifest.permission.ACTIVITY_RECOGNITION

           ) == PackageManager.PERMISSION_DENIED

       ) {

           if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {

               requestPermissions(arrayOf(Manifest.permission.ACTIVITY_RECOGNITION), 1001)

           }

       }

 

       sensorManager = getSystemService(SensorManager::class.java)

 

       setContent {

           SensorExamTheme {

               Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colors.background{

                   StepCounterUI()

               }

           }

       }

   }

 

   val customFontFamily FontFamily(

       Font(R.font.one_mobile_pop_otf, FontWeight.Normal),

       // Add other font variations if necessary

   )

 

 

   @Composable

   fun StepCounterUI() {

       Box(

           modifier = Modifier

               .fillMaxSize()

               .background(Color.White),

           contentAlignment = Alignment.TopCenter

       {

           Column(

               horizontalAlignment = Alignment.CenterHorizontally,

               verticalArrangement = Arrangement.Top

           {

               Box(

                   modifier = Modifier

                       .height(30.dp)

                       .fillMaxWidth()

                       .background(Color(0xFFFF6F00))

               )

               Box(

                   modifier = Modifier

                       .height(15.dp)

                       .fillMaxWidth()

                       .background(Color(0xFF595959))

               )

 

               Row(

                   modifier = Modifier

                       .fillMaxWidth()

                       .padding(top = 30.dp),

                   verticalAlignment = Alignment.CenterVertically,

                   horizontalArrangement = Arrangement.Center

               {

                   Text(

                       text = "이랜서",

                       fontSize = 35.sp,

                       fontWeight = FontWeight.Bold,

                       fontFamily = customFontFamily,

                       color = Color.Black

                   )

                   Spacer(modifier = Modifier.width(10.dp)) // Add some space between the texts

                   Text(

                       text = "LEARN & RUN",

                       fontSize = 35.sp,

                       fontWeight = FontWeight.Bold,

                       fontFamily = customFontFamily,

                       color = Color(0xFFFF6F00)

                   )

               }

 

               Text(

                   text = "'배우면서 달린다. 달리면서 배운다'",

                   fontSize = 24.sp,

                   fontFamily = customFontFamily,

                   color = Color(0xFF797979)

               )

 

               // Image

               val image: Painter = painterResource(id = R.drawable.logo)

               Image(

                   painter = image,

                   contentDescription = "Logo",

                   contentScale = ContentScale.FillWidth,

                   modifier = Modifier

                       .fillMaxWidth()

                       .padding(start = 16.dpend = 16.dp)

               )

 

               Row(

                   modifier = Modifier

                       .fillMaxWidth()

                       .padding(top = 16.dpstart = 16.dpend = 16.dpbottom = 8.dp),

                   verticalAlignment = Alignment.CenterVertically,

                   horizontalArrangement = Arrangement.Center

               {

                   Text(

                       text = stepValue.value,

                       Modifier.width(220.dp),

                       fontSize = 60.sp,

                       textAlign = TextAlign.End,

                       fontWeight = FontWeight.Bold,

                       fontFamily = customFontFamily,

                       color = Color(0xFFFF6F00)

                   )

 

                   Spacer(modifier = Modifier.width(20.dp)) // Add some space between the texts

                   Text(

                       text = "걸음",

                       fontSize = 40.sp,

                       fontWeight = FontWeight.Bold,

                       fontFamily = customFontFamily,

                   )

                   Spacer(modifier = Modifier.width(10.dp))

 

               }

 

               Box(

                   modifier = Modifier

                       .height(3.dp)

                       .padding(horizontal = 35.dp)

                       .fillMaxSize()

                       .background(Color(0xFF000000))

 

               )

 

               Row(

                   modifier = Modifier

                       .fillMaxWidth()

                       .padding(horizontal = 35.dp),

                   verticalAlignment = Alignment.CenterVertically,

               ) {

                   Text(

                       text = "총 7km",

                       fontSize = 25.sp,

                       fontFamily = customFontFamily,

                       color = Color.Black

                   )

                   Spacer(modifier = Modifier.width(5.dp)) // Add some space between the texts

                   Text(

                       text = "걸음",

                       fontSize = 25.sp,

                       fontFamily = customFontFamily,

                       color = Color(0xFFcacaca)

                   )

                   Spacer(modifier = Modifier.weight(1f))

                   Box(

                       modifier = Modifier

                           .clickable(onClick = {

                               _stepValue.value "0"

                           })

                           .padding(8.dp)

                           .width(100.dp)

                           .height(50.dp)

                           .background(Color(0xFFFF6F00), shape = RoundedCornerShape(8.dp)),

                       contentAlignment = Alignment.Center

                   {

                       // Additional content goes here

                       Text(

                           text = "Reset",

                           fontSize = 30.sp,

                           fontWeight = FontWeight.Bold,

                           fontFamily = customFontFamily,

                           color = Color(0xFFFFFFFF),

                       )

                   }

               }

 

               Spacer(modifier = Modifier.height(20.dp))

 

               // Placeholder for additional content

               Box(

                   modifier = Modifier

                       .padding(16.dp)

                       .fillMaxWidth()

                       .height(100.dp)

                       .background(Color(0xFFcacaca), shape = RoundedCornerShape(8.dp))

 

               ) {

                   // Additional content goes here

               }

 

               Spacer(modifier = Modifier.weight(1f))

 

               Box(

                   modifier = Modifier

                       .height(15.dp)

                       .fillMaxWidth()

                       .background(Color(0xFF595959))

               )

 

               Box(

                   modifier = Modifier

                       .height(30.dp)

                       .fillMaxWidth()

                       .background(Color(0xFFFF6F00))

               )

 

 

           }

       }

   }

 

   override fun onResume() {

       super.onResume()

       isRunning true

       val sensor = sensorManager?.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)

 

       sensor?.let {

           sensorManager?.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI)

       }

   }

 

   override fun onPause() {

       super.onPause()

       isRunning false

   }

 

   override fun onSensorChanged(event: SensorEvent?) {

       if (event != null) {

           val isIncrementStep = abs(event.values[0].toInt() - prevStep)

           prevStep event.values?.get(0)?.toInt()!!

           log("abs(event.values[0].toInt() - totalStep): $isIncrementStep :: ${isIncrementStep == 1}")

 

           if (isRunning && isIncrementStep == 1) {

               _stepValue.value = (++stepCount).toString()

           }

       }

   }

 

   override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}

 

   private fun log(msg: String) {

       Log.e(this.javaClass.simpleName, msg)

   }

}

 


 

만보기 어플 개발 결과

만보기-어플-추천

고객을 사로잡아 충성고객을 만드는 슈퍼 의 필수 기능 ‘만보기 어플’을 만들어 봤습니다. 걸음 수에 따라 숫자가 올라가는 만보기 어플이 완성된 것을 볼 수 있습니다. 

한 걸음 걸었을 때의 보폭 너비를 약 70cm로 잡았을 때 만보를 걸으면 7km를 걷게 되어, 총 7km 걸음이란 추가했습니다. 그리고 리셋 버튼까지 두어 매일 걸은 걸음을 기록하고 확인할 수 있습니다. 만보기 기능에 충실한 어플입니다.

 

어딘가 심심한 만보기 어플, 

기능 및 디자인 추가해 보았습니다.

요즘 빅 테크 기업은 고객에게 혜택을 주는 다양한 기능을 추가해 만보기 어플 사용을 촉진하고 있습니다. 빅 테크 기업을 따라 기능들을 추가하여 디자인을 해 보겠습니다. 

만보기-걸음-측정기

고객들이 만보기 기능을 지속적으로 사용하도록 목표 설정과 기록 보기 버튼을 추가했습니다. 목표 설정과 기록이 있을 경우 고객의 사용 빈도는 이전보다 높아지게 됩니다. 그리고 다중의 사람들과 함께 만보기 기능을 즐길 수 있도록 등급 확인 및 초대하기 및 포인트 받기 버튼을 추가했습니다. 

 

빅 테크 기업 및 금융 IT 기업들은 만보기 어플 외에도 다양한 기능을 추가하여 어플 사용도를 높여 어플 친숙도를 높이고 있습니다. 이를 통해 충성고객을 확보하여 메인 서비스의 사용 확률도 높이고 있는데요. 

 

 

잘나가는 빅 테크 기업들은 다양한 기능을 활용해 

충성고객을 사로잡고 있습니다.

 

온라인 비즈니스를 준비하는 기업 특히 모바일 시장에 진출을 앞둔 기업이라면 만보기 어플과 같은 락인 효과를 가진 슈퍼 앱을 준비한다면, 충성고객 확보와 더불어 성공적인 비즈니스 결과를 얻을 수 있게 될 것입니다.

 

 

이랜서 추천! 충성고객 확보를 위한  필승 공략 시리즈

▶️ 랜딩 페이지, 고객을 사로잡으려면 '이렇게' 만드세요

▶️ 고객 여정 지도, ‘N사‘ 서비스 기획자는 이렇게 만듭니다.

▶️ UX 디자인의 일관성을 높이는 디자인 시스템 가이드 작성 비법과 사례

 

 이랜서 추천! 알아두면 업무 효율이 높아지는 업무 효율 시리즈

▶️ 미드저니 사용법: 프롬프트 작성 가이드\

▶️ Chat GPT 엔지니어'가 사용하는 프롬프트 작성법

▶️ 코파일럿, 마이크로소프트 365의 AI 서비스가 일으킨 사무실 대혁명

 

 

 

경쟁이 치열해지는 모바일 비즈니스 시장,

이랜서와 함께라면 걱정 없습니다. 

만보기-기계

이랜서는 데이터로 검증된 IT 전문가를 매칭해주는 대한민국 최대  IT 인재 매칭 플랫폼입니다. 

모바일 앱 개발을 위한 Java, Kotlin, Swift, Xamarin 전문가와 플러터(Flutter), React Native, .Net을 활용하는 크로스 플랫폼 전문가, 서버 개발과 관리를 위한 JavaScript, Typescript, Node js, Spring, .NET 프레임워크을 활용하는 백엔드 개발자데이터 수집 & 활용을 위한 SQL 전문가(Oracle, Mysql, MS SQL 등) 그리고 고객 여정 지도와 수준 높은 UX 디자인을 구사하여 충성고객 확보를 도울 서비스 기획자UX/UI 전문 디자이너까지 약 40만 명의 IT 전문 프리랜서가 파트너십으로 등록되어 있습니다.


 

“다른 회사에 비해서 추천 인력의 퀄리티가 높습니다.”

이랜서는 이랜서만의 체계적인 프로세스와 DB를 활용하여 IT 전문가를 매칭합니다. 이랜서를 활용하는 기업들은 다른 플랫폼에서는 찾을 수 없는 퀄리티 높은 IT 전문가를 매칭 받고 있습니다.

 

서버-사이드-랜더링
 
 

개발부터 디자인, 기획, 유지보수까지

맞춤형 매칭 서비스로 필요한 IT 전문가를 빠르게 매칭합니다.


 

이랜서는 기업들이 IT 전문가 채용 시 겪는 어려움을 해결하기 위해, 약 1.5억 개의 서비스데이터350만 개의 프리랜서 평가 데이터를 활용하여, 전문성부터 인성(협업 능력)까지 철저하게 확인하여 프로젝트에 가장 적합한 IT 전문가를 매칭합니다.

 

또한 프로젝트 등록 시 1:1로 매니저를 배정하여, 프로젝트 등록 24시간 이내 프로젝트에 가장 적합한 IT 전문가를 데이터로 검증하여 매칭합니다.

 

wbs-템플릿
 
 

전문성과 인성이 데이터로 모두 검증된 자바 개발자를 찾으시나요?


 

대한민국 No.1 IT 인재 매칭 플랫폼 이랜서

-> 회원 가입만 하세요.

-> 24시간 안에 전담 매니저가 연락을 드립니다.

-> 끝입니다. 이게 다냐구요? 네, 이게 다입니다.

-> 급하시다고요? 전화 주세요. 02-545-0042

 

24년의 노하우 데이터를 바탕으로 검증된 IT 프리랜서를 매칭해 드립니다.

 

freelancerBanner
projectBanner
댓글0
이랜서에 로그인하고 댓글을 남겨보세요!
0
/200
이랜서에 로그인하고 댓글을 남겨보세요!
0
/200
실시간 인기 게시물
이랜서 PICK 추천 게시물