๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿค2024 ์•ˆ๋“œ๋กœ์ด๋“œ/๐Ÿฟ ์˜ํ™” ํ”„๋กœ์ ํŠธ ๊ฐœ๋ฐœ ์ผ์ง€

๐Ÿซ™Android ๋กœ๊ทธ์ธ ํ† ํฐ ์ €์žฅ : Proto Datastore ์ ์šฉํ•˜๊ธฐ

by hyeonha 2024. 3. 15.

๋ชฉ์ฐจ

    Proto Datastore ๊ฐœ๋… ์ดํ•ดํ•˜๊ธฐ

    Jetpack์˜ Datastore์€ ํ”„๋กœํ† ์ฝœ ๋ฒ„ํผ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ‚ค-๊ฐ’ ์Œ ๋˜๋Š” ์œ ํ˜•์ด ์ง€์ •๋œ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ ์ €์žฅ์†Œ ์†”๋ฃจ์…˜์ด๋‹ค. 

    Datastore์€ kotlin์˜ ์ฝ”๋ฃจํ‹ด ๋ฐ Flow๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„๋™๊ธฐ์ ์ด๊ณ  ์ผ๊ด€๋œ ํŠธ๋žœ์žญ์…˜ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•œ๋‹ค. 

     

    ์ด ๋•Œ 2๊ฐ€์ง€์˜ ์ €์žฅ์†Œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

    1๏ธโƒฃProto Datastore : ๋งž์ถค ๋ฐ์ดํ„ฐ ์œ ํ˜•์˜ ์ธ์Šคํ„ด์Šค๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•œ๋‹ค. ์œ ํ˜• ์•ˆ์ „์„ฑ์„ ์ œ๊ณตํ•˜๋ฉฐ ํ”„๋กœํ† ์ฝœ ๋ฒ„ํผ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์Šคํ‚ค๋งˆ๋ฅผ ์ •์˜ํ•œ๋‹ค.

    2๏ธโƒฃPreferences Datastore : ํ‚ค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ์— ์ €์žฅ & ์•ก์„ธ์Šค๋ฅผ ํ•œ๋‹ค ์œ ํ˜• ์•ˆ์ „์„ฑ์„ ์ œ๊ณตํ•˜์ง€ ์•Š์œผ๋ฉฐ ์‚ฌ์ „์— ์ •์˜๋œ ์Šคํ‚ค๋งˆ๊ฐ€ ํ•„์š”ํ•˜์ง€ ์•Š๋‹ค.

     

     

    โ“ ์œ ํ˜• ์•ˆ์ „์„ฑ์„ ์ œ๊ณตํ•˜๋ฉด ๋ฌด์—‡์ด ๋‹ค๋ฅธ๊ฑธ๊นŒ?

    ๐Ÿ—จ๏ธํ”„๋กœ๊ทธ๋žจ์—์„œ ๋ฐ์ดํ„ฐ ์œ ํ˜•์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๋„๋ก ๋ณด์žฅํ•˜๋Š” ๊ฐœ๋…์ด๋‹ค. ์ฆ‰ ๋ณ€์ˆ˜์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•ด๋‹น ๋ณ€์ˆ˜์˜ ์œ ํ˜•๊ณผ ์ผ์น˜ํ•˜๋Š”์ง€๋ฅผ ํ™•์ธํ•œ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์ปดํŒŒ์ผ ์‹œ์ ์— ๋ฐ์ดํ„ฐ ์œ ํ˜• ์˜ค๋ฅ˜๋ฅผ ๊ฐ์ง€ํ•˜์—ฌ ์ฝ”๋“œ ์˜ค๋ฅ˜๋ฅผ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

     

    โ“ ํ”„๋กœํ† ์ฝœ ๋ฒ„ํผ๋ž€?

    ๐Ÿ—จ๏ธ ๊ตฌ์กฐํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ง๋ ฌํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์˜๋ฏธํ•œ๋‹ค. 

     

    โ“  ์Šคํ‚ค๋งˆ๋ž€?

    ๐Ÿ—จ๏ธ ์Šคํ‚ค๋งˆ๋Š” ๋ฉ”์‹œ์ง€์˜ ๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•˜๋Š” ๊ทœ์น™์„ ์˜๋ฏธํ•œ๋‹ค. 

     

    protobuf ๊ฐ์ฒด ์ •์˜ ๋ฐ ์‚ฌ์šฉ

    Proto Datastore ๊ตฌํ˜„์€ Datastore ๋ฐ ํ”„๋กœํ† ์ฝœ ๋ฒ„ํผ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์œ ํ˜•์ด ์ง€์ •๋œ ๊ฐ์ฒด๋ฅผ ๋””์Šคํฌ์— ์œ ์ง€ํ•œ๋‹ค.

    1๏ธโƒฃ proto ํŒŒ์ผ ๋งŒ๋“ค๊ธฐ - ์Šคํ‚ค๋งˆ ์ •์˜ํ•˜๊ธฐ

    proto ํŒŒ์ผ์—์„œ ์Šคํ‚ค๋งˆ๋ฅผ ์ •์˜ํ•ด์ค€๋‹ค. 

    proto๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉฐ app/src/main/proto/ ๋””๋ ‰ํ„ฐ๋ฆฌ์˜ proto ํŒŒ์ผ์— ์‚ฌ์ „ ์ •์˜๋œ ์Šคํ‚ค๋งˆ๊ฐ€ ์žˆ์–ด์•ผํ•œ๋‹ค. 

    ์‚ฌ์ „ ์ •์˜๋œ ์Šคํ‚ค๋งˆ๋Š” Proto์— ์œ ์ง€ํ•˜๋Š” ๊ฐ์ฒด์˜ ์œ ํ˜•์„ ์ •์˜ํ•œ๋‹ค. 

    ์šฐ๋ฆฌ๋Š” ๋กœ๊ทธ์ธ ์š”์ฒญ ์‹œ ์‘๋‹ต์œผ๋กœ ์˜ค๋Š” access token๊ณผ refresh token ๋‘ ๊ฐ€์ง€์˜ ๊ฐ์ฒด๋ฅผ ํ‘œํ˜„ํ•ด์ค€๋‹ค.

    DataStore์— ์ €์žฅ๋œ UserToken ํด๋ž˜์Šค ์•„๋ž˜์— ์ด ๋‘ ํ”Œ๋ž˜๊ทธ๋ฅผ ํ†ตํ•ฉํ•ด์ฃผ์—ˆ๋‹ค. 

     

    ์ด ๋•Œ protobuf์˜ ๊ฐ ๊ตฌ์กฐ๋Š” message ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ •์˜ํ•œ๋‹ค.

    ๊ตฌ์กฐ์˜ ๊ฐ ์š”์†Œ๋Š” ์œ ํ˜•๊ณผ ์ด๋ฆ„์— ๋”ฐ๋ผ ๋ฉ”์‹œ์ง€ ๋‚ด์— ์ •์˜๋˜๋ฉฐ 1๋ถ€ํ„ฐ ์ฐจ๋ก€๋Œ€๋กœ ์ˆœ์„œ๊ฐ€ ํ• ๋‹น๋œ๋‹ค. 

    syntax = "proto3";
    
    option java_package = "com.teamfilmo.filmo.data.local.model";
    option java_multiple_files = true;
    
    message UserToken {
        string access_token = 1;
        string refresh_token = 2;
    }

     

    Proto ์Šคํ‚ค๋งˆ๋ฅผ ์ •์˜ํ•˜๋Š” ๋ฐฉ๋ฒ• 

    1๏ธโƒฃ์ฒซ๋ฒˆ์งธ ์ค„์— proto3 systax์„ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ์ ์–ด์ค€๋‹ค. ๋งŒ์•ฝ ์ ์–ด์ฃผ์ง€ ์•Š์œผ๋ฉด ํ”„๋กœํ† ์ฝœ ๋ฒ„ํผ ์ปดํŒŒ์ผ๋Ÿฌ๋Š” proto2๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค.

    2๏ธโƒฃUserToken message ์ •์˜๋Š” access_token๊ณผ refresh_token 2๊ฐ€์ง€์˜ ํ•„๋“œ๋ฅผ ์ง€์ •ํ•œ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฉ”์‹œ์ง€์— ํฌํ•จํ•˜๊ณ  ์‹ถ์€ ๋ฐ์ดํ„ฐ ๊ฐ๊ฐ์˜ ํ•„๋“œ๋Š” ์ด๋ฆ„๊ณผ ํƒ€์ž…์„ ๊ฐ€์ง„๋‹ค. 

    3๏ธโƒฃํ•„๋“œ์—๋Š” ์ˆ˜๋ฅผ ์ง€์ •ํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค. ์ด ๋•Œ ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ ์œ ์ผํ•ด์•ผํ•œ๋‹ค(unique) 

     

    ์ด๋ ‡๊ฒŒ proto ํŒŒ์ผ์— ์ •์˜ํ•˜๊ณ  ํ”„๋กœ์ ํŠธ๋ฅผ ๋‹ค์‹œ ๋นŒ๋“œํ•˜๋ฉด UserToken message๋Š” ์ปดํŒŒ์ผ ์‹œ๊ฐ„์— ๊ฐ์ฒด์˜ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. 

     

    โฃ๏ธ ์ฒ˜์Œ์— ์ฝ”๋“œ๋ฅผ ๋ฐ›์•˜์„ ๋•Œ๋Š” ์ •์˜๋œ UserToken ํด๋ž˜์Šค๊ฐ€ ์—†์–ด์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜์˜€๋‹ค. ๊ทธ๋ž˜์„œ ๊ฐœ๋ฐœ์ž๋ถ„๊ป˜ ํŒŒ์ผ์ด ์—†๋‹ค๊ณ  ์งˆ๋ฌธ์„ ๋“œ๋ ธ๊ณ , ๋นŒ๋“œ ํ›„์— ์ƒ์„ฑ๋œ๋‹ค๋Š” ๋‹ต๋ณ€์„ ๋ฐ›์•˜๋‹ค. ๊ทธ ์ด์œ ๊ฐ€ ์œ„์™€ ๊ฐ™์•˜๋‹ค!!

     

    ์ด์ œ ์ด๋ ‡๊ฒŒ ์œ ํ˜•์ด ์ง€์ •๋œ UserToken ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•ด์ค„ Proto Datastore์„ ๋งŒ๋“ค์–ด์ฃผ์ž. ์ €์žฅํ•ด์ฃผ๊ธฐ ์œ„ํ•ด์„œ๋Š” 2๋‹จ๊ณ„๋ฅผ ๊ฑฐ์ณ์•ผํ•œ๋‹ค. 

    - Serializer<T>๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ํด๋ž˜์Šค ์ •์˜ํ•˜๊ธฐ

    - dataStore๋กœ ๋งŒ๋“  ์†์„ฑ ์œ„์ž„์„ ์‚ฌ์šฉํ•˜์—ฌ DataStore<T >์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.

     

    ์—ฌ๊ธฐ์„œ T๋Š”  proto ํŒŒ์ผ์— ์ •์˜๋œ ์œ ํ˜•์„ ์˜๋ฏธํ•œ๋‹ค. 

     

    ์•„๋ž˜์˜  seirializer ๋งŒ๋“ค๊ธฐ  ๋‚ด์šฉ๋ถ€ํ„ฐ ์‚ดํŽด๋ณด์ž!

     

    2๏ธโƒฃserializer ๋งŒ๋“ค๊ธฐ

    proto ํŒŒ์ผ์— ์ •์˜ํ•œ ๋ฐ์ดํ„ฐ ์œ ํ˜• ( access_token๊ณผ refresh_token์„ ์ฝ๊ณ  ์“ฐ๋Š” ๋ฐฉ๋ฒ•์„ Datastore์— ์•Œ๋ฆฌ๋ ค๋ฉด serializer์„ ๊ตฌํ˜„ํ•ด์•ผํ•œ๋‹ค. serializer ํด๋ž˜์Šค๊ฐ€ ๋ฐ์ดํ„ฐ ์œ ํ˜•์„ ์ฝ๊ณ  ์“ฐ๋Š” ๋ฐฉ๋ฒ•์„ Datastore์— ์•Œ๋ ค์ฃผ๋Š” ์—ญํ• ์„ ํ•œ๋‹ค.

    ๋˜ํ•œ serializer๋Š” ๋””์Šคํฌ์— ๋ฐ์ดํ„ฐ๊ฐ€ ์—†์„ ๋•Œ(ํŒŒ์ผ์ด ์ƒ์„ฑ๋˜์ง€ ์•Š์„ ๊ฒฝ์šฐ) ๋ฐ˜ํ™˜๋  seriazlier๊ธฐ๋ณธ๊ฐ’๋„ ์ •์˜ํ•ด์ฃผ์–ด์•ผํ•œ๋‹ค.

     

    object UserTokenSerializer : Serializer<UserToken> {
        private val TAG = this::class.java.simpleName
    
        override val defaultValue: UserToken
            get() = UserToken.getDefaultInstance()
    
        override suspend fun readFrom(input: InputStream): UserToken {
            try {
                return UserToken.parseFrom(input)
            } catch (e: InvalidProtocolBufferException) {
                throw CorruptionException("Cannot read proto.", e)
            }
        }
    
        override suspend fun writeTo(
            t: UserToken,
            output: OutputStream,
        ) {
            t.writeTo(output)
        }
    }
    

     

    ์ด์ œ ์•ž์„œ ๋งํ–ˆ๋˜ DataStore<T>์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์–ด์ค„ ์ฐจ๋ก€์ด๋‹ค. ์•„๋ž˜์˜ ๋‚ด์šฉ๋„ ์‚ดํŽด๋ณด์ž

    Proto Datastore์—์„œ ๋ฐ์ดํ„ฐ ์œ ์ง€

    1๏ธโƒฃDatastore ๋งŒ๋“ค๊ธฐ

    access_token๊ณผ refresh_token์€ Datastore ๊ฐ์ฒด์˜ AuthRepository์— ์ €์žฅ๋˜์–ด์•ผํ•œ๋‹ค.

    Datastore ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด dataStore ์œ„์ž„์„ ์‚ฌ์šฉํ•˜์—ฌ ์ˆ˜์‹ ๊ธฐ๋กœ Context๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. 

     

    ์ด ์œ„์ž„์—๋Š” ๋‘๊ฐ€์ง€ ํ•„์ˆ˜ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์žˆ๋‹ค.

    - Datastore๊ฐ€ ์ž‘๋™ํ•  ํŒŒ์ผ์˜ ์ด๋ฆ„ : user_token_pb 

        -> ์ด๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•  ํŒŒ์ผ์„ Datastore์— ์•Œ๋ ค์ค€๋‹ค.

    - Datastore์—์„œ ์‚ฌ์šฉ๋˜๋Š” ์œ ํ˜•์„ ์œ„ํ•œ serializer : UserTokenSerializer

        -> ์ด๋Š” ์•ž์„œ ์ •์˜ํ•ด์ค€ serializer ํด๋ž˜์Šค์˜ ์ด๋ฆ„์„ Datastore์— ์•Œ๋ ค์ค€๋‹ค.

     

    object DataStoreConfig {
        const val USER_TOKEN_DATA_STORE_FILE_NAME = "user_token.pb"
    }
    
    val Context.userToken: DataStore<UserToken> by dataStore(
        fileName = DataStoreConfig.USER_TOKEN_DATA_STORE_FILE_NAME,
        serializer = UserTokenSerializer,
    )
    

     

     

    dataStore ์œ„์ž„์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ์ด ์ด๋ฆ„์„ ๊ฐ€์ง„ Datastore ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•˜๋‚˜๋งŒ ์žˆ์Œ์„ ๋ณด์žฅํ•ด์ค€๋‹ค. ํ˜„์žฌ AuthRepository๋Š” ์ƒ์„ฑ์ž ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ DataStore ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€์ ธ์™€์•ผํ•œ๋‹ค. 

    ์šฐ๋ฆฌ๋Š” di๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด ๋ชจ๋“ˆ๋กœ ์ •์˜ํ•ด๋‘์—ˆ๋‹ค.

    @Module
    @InstallIn(SingletonComponent::class)
    object LocalModule {
        @Provides
        fun provideDataStoreUserToken(
            @ApplicationContext context: Context,
        ): DataStore<UserToken> {
            return context.userToken
        }
    }
    

     

    2๏ธโƒฃ Proto Datastore์—์„œ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ 

    ๊ตฌํ˜„ํ•ด์ค„ ํ•จ์ˆ˜๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค๋กœ ์ •์˜ํ•ด์ค€๋‹ค. 

    interface UserTokenSource {
        fun getUserToken(): Flow<String>
    
        suspend fun setUserToken(token: String)
    
        fun getRefreshToken(): Flow<String>
    
        suspend fun setRefreshToken(token: String)
    
        suspend fun updateToken(
            accessToken: String,
            refreshToken: String,
        )
    
        suspend fun clearUserToken()
    }
    

     

    Proto Datastore์€ Flow<UserToken>์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋…ธ์ถœํ•œ๋‹ค. 

    DataStore.data๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ €์žฅ๋œ ๊ฐ์ฒด์—์„œ ์ ์ ˆํ•œ ์†์„ฑ์˜ Flow๋ฅผ ๋…ธ์ถœํ•œ๋‹ค. 

    class UserTokenSourceImpl
        @Inject
        constructor(
            private val dataStore: DataStore<UserToken>,
        ) : UserTokenSource {
            override fun getUserToken(): Flow<String> {
                return dataStore.data.map {
                    it.accessToken
                }
            }
    
            override suspend fun setUserToken(token: String) {
                dataStore.updateData {
                    it.copy {
                        accessToken = token
                    }
                }
            }
    
            override fun getRefreshToken(): Flow<String> {
                return dataStore.data.map {
                    it.refreshToken
                }
            }
    
            override suspend fun setRefreshToken(token: String) {
                dataStore.updateData {
                    it.copy {
                        refreshToken = token
                    }
                }
            }
    
            override suspend fun updateToken(
                accessToken: String,
                refreshToken: String,
            ) {
                dataStore.updateData {
                    it.copy {
                        this.accessToken = accessToken
                        this.refreshToken = refreshToken
                    }
                }
            }
    
            override suspend fun clearUserToken() {
                dataStore.updateData {
                    userToken {
                        clearAccessToken()
                        clearRefreshToken()
                    }
                }
            }
        }
    

     

    Proto Datastore์— ๋ฐ์ดํ„ฐ ์“ฐ๊ธฐ

     

    ๋ฐ์ดํ„ฐ๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋„๋ก suspend ์ •์ง€ ํ•จ์ˆ˜์ธ DataStore.updateData ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์žˆ๋‹ค. ์ด ํ•จ์ˆ˜์—์„œ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ token์„ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฅผ ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ๋ ค๋ฉด UserToken.copy๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  ์ƒˆ๋กœ์šด token์œผ๋กœ accessToken์„ ์—…๋ฐ์ดํŠธ ํ•ด์ค€๋‹ค. 

     

    updateData( )๋Š” ๋ฐ์ดํ„ฐ์˜ ํ˜„์žฌ ์ƒํƒœ๋ฅผ ๋ฐ์ดํ„ฐ ์œ ํ˜•์˜ ์ธ์Šคํ„ด์Šค๋กœ ์ œ๊ณตํ•˜๊ณ  ์›์ž์  ์ฝ๊ธฐ-์“ฐ๊ธฐ-์ˆ˜์ • ์ž‘์—…์„ ํ†ตํ•ด ํŠธ๋žœ์žญ์…˜ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค. ์ฝ”๋ฃจํ‹ด์€ ๋ฐ์ดํ„ฐ๊ฐ€ ๋””์Šคํฌ์— ์œ ์ง€๋˜๋ฉด ์™„๋ฃŒ๊ฐ€ ๋œ๋‹ค.

    override suspend fun setUserToken(token: String) {
        dataStore.updateData {
            it.copy {
                accessToken = token
            }
        }
    }

     

    โ“๊ณต์‹๋ฌธ์„œ๋Š” toBuilder( )๋ฅผ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•œ๋‹ค. ์šฐ๋ฆฌ ์ฝ”๋“œ๋Š” .copy( )๋ฅผ ์‚ฌ์šฉํ•˜๋Š”๋ฐ ์ด ๋‘๊ฐ€์ง€ ๋ฐฉ์‹์˜ ์ฐจ์ด๋Š” ๋ญ˜๊นŒ?

    ๐Ÿ—จ๏ธ toBuilder()์™€ copy()๋Š” ๋ชจ๋‘ ๊ฐ์ฒด๋ฅผ ๋ณต์‚ฌํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋˜๋Š” ํ•จ์ˆ˜์ด๋‹ค. ์ฐจ์ด๋ฅผ ์•Œ์•„๋ณด์ž

     

    ๊ฐ์ฒด ๋ณ€๊ฒฝ ๋ฐฉ์‹

    -  toBuilder( )๋Š” ๊ฐ์ฒด์˜ ๋นŒ๋”๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๋นŒ๋”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด์˜ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•œ ํ›„ build() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถ”๋ž—๋ฉฐ ์ƒˆ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

    - copy()๋Š” ๊ฐ์ฒด์˜ ์ƒˆ๋กœ์šด ๋ณต์‚ฌ๋ณธ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ƒˆ ๋ณต์‚ฌ๋ณธ์—๋Š” ์›๋ณธ ๊ฐ์ฒด์˜ ๋ชจ๋“  ์†์„ฑ๊ฐ’์ด ํฌํ•จ๋œ๋‹ค. ์ด๋•Œ ๋ณ€๊ฒฝํ•˜๋ ค๋Š” ์†์„ฑ๊ฐ’์„ ์ง์ ‘ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

     

    ์„ฑ๋Šฅ

    - toBuilder()๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๊ฐ์ฒด์˜ ๋ชจ๋“  ์†์„ฑ์„ ๋ณต์‚ฌํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— copy()๋ณด๋‹ค ์„ฑ๋Šฅ์ด ๋‚ฎ๋Œœ.

    - copy()๋ฅผ ํ†ตํ•ด ๋งŒ๋“ค์–ด์ง„ ์ƒˆ ๋ณต์‚ฌ๋ณธ์—๋Š” ์›๋ณธ ๊ฐ์ฒด์˜ ๋ชจ๋“  ์†์„ฑ ๊ฐ’์ด ํฌํ•จ๋˜์ง€๋งŒ ๋ณ€๊ฒฝํ•˜๋ ค๋Š” ์†์„ฑ ๊ฐ’๋งŒ ๋ณต์‚ฌํ•˜๋ฉด ๋œ๋‹ค. ์ด๋Š” toBuilder()๋ณด๋‹ค ์„ฑ๋Šฅ์ด ๋†’์€ ํŽธ์ด๋‹ค.

     

    ์œ ์šฉํ•œ ์ƒํ™ฉ

    - toBuilder()๋Š” ๋ณต์žกํ•œ ๋ณ€๊ฒฝ์„ ์ˆ˜ํ–‰ํ•  ๋•Œ ๋” ์œ ํ˜•ํ•œ๋‹ค. ๋นŒ๋”๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—ฌ๋Ÿฌ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ ์กฐ๊ฑด๋ถ€๋กœ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

    - copy()๋Š” ๊ฐ„๋‹จํ•œ ๋ณ€๊ฒฝ์„ ์ˆ˜ํ–‰ํ•  ๋•Œ ๋” ์œ ์šฉํ•˜๋‹ค. ํ•œ๋‘๊ฐœ์˜ ์†์„ฑ์„ ๋ณ€๊ฒฝํ•ด์•ผํ•˜๋Š” ๊ฒฝ์šฐ copy()๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๊ฐ„๋‹จํ•˜๋‹ค.

     

    ์šฐ๋ฆฌ ์ฝ”๋“œ์— ๋” ์ ์ ˆํ•œ ๊ฒƒ์€?

    ์šฐ๋ฆฌ๋Š” accessToken ์†์„ฑ๋งŒ ๋ณ€๊ฒฝํ•˜๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— copy()๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๊ฐ„๋‹จํ•˜๊ณ  ์ง๊ด€์ ์ด๋‹ค. 

    728x90