Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
c56e4fe
[fix]: BuildConfig 오류 해결을 위한 android.defaults.buildfeatures.buildconf…
JJUYAAA Aug 11, 2025
95ca8c8
[feat]: 카카오 - 신규유저 여부 확인 api 요청, 응답 dto(#68)
JJUYAAA Aug 12, 2025
e80c3a5
[feat]: 카카오 - AuthService 생성(#68)
JJUYAAA Aug 12, 2025
a4c5c28
[feat]: 카카오 - AuthRepository 생성(#68)
JJUYAAA Aug 12, 2025
48014b0
[feat]: 카카오 로그인 관련 의존성 추가(#68)
JJUYAAA Aug 12, 2025
e00e585
[feat]: loginscreen - content와 screen(뷰모델 주입받음) 분리 (#68)
JJUYAAA Aug 12, 2025
cdff7a0
[feat]: 카카오 로그인에 필요한 maven 설정 (#68)
JJUYAAA Aug 12, 2025
9a67f61
[feat]: lifecycle 라이브러리 재설치 (#68)
JJUYAAA Aug 12, 2025
56144a0
[feat]: 카카오로그인 뷰모델 생성(#68)
JJUYAAA Aug 12, 2025
e78a120
[feat]:common routes에 로그인 회원가입 관련 스크린 루트 추가(#68)
JJUYAAA Aug 12, 2025
9833a07
[feat]: 토큰매니절 생성(#68)
JJUYAAA Aug 12, 2025
5b5b7e3
[feat]: 신규유저인 경우 피드화면으로 이동하는 로직 테스트 후 주석처리(#68)
JJUYAAA Aug 12, 2025
9b4c045
[feat]: 신규유저 여부에 따라 카카오로그인 후 화면이동 설정(#68)
JJUYAAA Aug 12, 2025
d846745
[feat]: 네크워크모듈 - auth 서비스 추가(#68)
JJUYAAA Aug 12, 2025
fe5f3bb
[feat]: 인터넷 권한 추가(#68)
JJUYAAA Aug 12, 2025
7befae5
[feat]: 네이티브앱 주입하는 코드들 (#68)
JJUYAAA Aug 12, 2025
f39127a
[refactor]: provideAuthService 네트워크 모듈-> 서비스 모듈 이동(#68)
JJUYAAA Aug 12, 2025
5a5c765
[refactor]: NATIVE_APP_KEY 관련 수정사항 반영(#68)
JJUYAAA Aug 12, 2025
d8310aa
[refactor]: NATIVE_APP_KEY 관련 수정사항 반영(#68)
JJUYAAA Aug 12, 2025
fafe4d2
[refactor]: inject import문 변경(#68)
JJUYAAA Aug 12, 2025
8638197
[refactor]: 카카오 sdk 초기화 -> 예외처리 추가(#68)
JJUYAAA Aug 12, 2025
c5ec891
Merge branch 'develop' into feat/#68-social_login_kakao
Nico1eKim Aug 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ android {
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

buildConfigField("String", "BASE_URL", "\"${properties["BASE_URL"]}\"")
buildConfigField("String", "NATIVE_APP_KEY", "\"${properties["NATIVE_APP_KEY"]}\"")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

local.properties 미설정 시 “null” 문자열이 주입될 수 있습니다. 강제 검증 로직으로 빌드를 fail-fast 하세요.

현재 properties["NATIVE_APP_KEY"]가 없으면 "null" 문자열이 들어갈 수 있습니다. 빌드 시점에 존재 여부를 검증하고 없으면 명시적으로 실패시키는 것이 안전합니다.

선택 범위 내 변경(diff):

-        buildConfigField("String", "NATIVE_APP_KEY", "\"${properties["NATIVE_APP_KEY"]}\"")
+        buildConfigField("String", "NATIVE_APP_KEY", "\"$nativeAppKey\"")

선택 범위 밖에 필요한 보조 코드(상단 프로퍼티 로드 직후):

val nativeAppKey = properties.getProperty("NATIVE_APP_KEY")
    ?: throw GradleException("Missing NATIVE_APP_KEY in local.properties")
🤖 Prompt for AI Agents
In app/build.gradle.kts around line 30, the buildConfigField uses
properties["NATIVE_APP_KEY"] which can inject the literal "null" when the key is
absent; add a fail-fast check immediately after loading properties: read the
value with properties.getProperty("NATIVE_APP_KEY"), and if it's null throw a
GradleException("Missing NATIVE_APP_KEY in local.properties"), then use that
validated variable in buildConfigField so the build explicitly fails when the
key is not set.

manifestPlaceholders += mapOf(
"NATIVE_APP_KEY" to properties["NATIVE_APP_KEY"] as String
)
}

buildTypes {
Expand Down Expand Up @@ -68,6 +72,7 @@ dependencies {
implementation(libs.kotlinx.serialization.json)
implementation(libs.coil.compose)
implementation(libs.foundation)
implementation(libs.androidx.lifecycle.runtime.compose)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

알파 채널 의존성 사용 주의: lifecycle-runtime-compose는 안정 버전으로 정렬 권장

여기서 사용하는 libs.androidx.lifecycle.runtime.compose가 toml에서 2.10.0-alpha01로 지정되어 있습니다. 다른 라이프사이클 라이브러리와 안정 버전으로 맞추는 게 안전합니다. toml의 lifecycleRuntimeCompose 버전을 안정 버전으로 내리고, 여기 의존성은 그대로 alias를 사용하세요.

위 파일 코멘트에 남긴 웹 검색으로 최신 안정 버전을 확인해 주세요.


먼저 libs.versions.toml에서 lifecycleRuntimeCompose가 어떤 버전으로 지정되어 있는지 확인하고, 이어서 최신 안정 버전을 웹에서 조회합니다.


🏁 Script executed:

#!/bin/bash
# 버전 카탈로그 파일 경로 찾기
catalog=$(fd --hidden --ignore-case "libs.versions.toml" | head -n1)
if [[ -n "$catalog" ]]; then
  echo "== $catalog 에서 lifecycleRuntimeCompose 버전 추출 =="
  rg "lifecycleRuntimeCompose" -n "$catalog"
else
  echo "Error: libs.versions.toml 파일을 찾을 수 없습니다."
fi

Length of output: 525


🌐 Web query:

androidx.lifecycle:lifecycle-runtime-compose latest stable version

💡 Result:

The latest stable version is 2.9.2 (released July 16, 2025). (developer.android.com, mvnrepository.com)

Gradle (Groovy):
implementation "androidx.lifecycle:lifecycle-runtime-compose:2.9.2"

Gradle (Kotlin DSL):
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.9.2")

This artifact is published on Google’s Maven repository, so ensure you have google() in your repositories. (mvnrepository.com, developer.android.com)

Would you like the Maven XML snippet or the corresponding lifecycle/viewmodel-compose version info as well?

Citations:


안정 버전 사용 권장: lifecycle-runtime-compose 2.9.2로 변경

아래와 같이 버전 카탈로그를 안정 버전으로 롤백하고, build.gradle.kts에서는 기존 alias 사용을 유지하세요.

• gradle/libs.versions.toml (28행)

- lifecycleRuntimeCompose = "2.10.0-alpha01"
+ lifecycleRuntimeCompose = "2.9.2"

• app/build.gradle.kts (72행)

implementation(libs.androidx.lifecycle.runtime.compose)
🤖 Prompt for AI Agents
In app/build.gradle.kts around line 72, keep the existing alias usage
(implementation(libs.androidx.lifecycle.runtime.compose)) but update the version
in gradle/libs.versions.toml (around line 28) to the stable
lifecycle-runtime-compose 2.9.2; edit the TOML entry to set the version to
"2.9.2" so the alias continues to resolve to the stable release without changing
build.gradle.kts.

implementation(libs.androidx.datastore.preferences)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
Expand All @@ -91,6 +96,12 @@ dependencies {
// OkHttp
implementation(libs.okhttp)
implementation(libs.logging.interceptor)

// 카카오 로그인 SDK
implementation("com.kakao.sdk:v2-all:2.21.6")

// 토큰 저장을 위한 DataStore
implementation ("androidx.datastore:datastore-preferences:1.1.1")
}

kapt {
Expand Down
24 changes: 22 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">


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

<application
android:name=".ThipApplication"
android:allowBackup="true"
Expand All @@ -14,6 +16,25 @@
android:supportsRtl="true"
android:theme="@style/Theme.Thip"
tools:targetApi="31">

<meta-data
android:name="com.kakao.sdk.AppKey"
android:value="${NATIVE_APP_KEY}" />
Comment on lines +20 to +22
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Manifest placeholder 주입 경로 확인 필요 (${NATIVE_APP_KEY})

Manifest의 meta-data 값에 ${NATIVE_APP_KEY} placeholder를 사용하고 있는데, app/build.gradle(.kts)의 defaultConfig.manifestPlaceholders["NATIVE_APP_KEY"]에 실제 값이 매핑되지 않으면 런타임에 그대로 문자열로 남아 Kakao SDK 초기화가 실패합니다. BuildConfig 필드와 Manifest placeholder는 별개이므로, manifestPlaceholders를 명시적으로 설정했는지 확인해 주세요. 필요하다면 설정 스니펫 제공 가능합니다.

다음 스크립트로 설정 여부를 점검해 주세요:


🏁 Script executed:

#!/bin/bash
# manifestPlaceholders에 NATIVE_APP_KEY 정의 여부 확인
fd build.gradle.kts -a | while read -r f; do
  echo ">>> $f"
  rg -n "manifestPlaceholders" "$f" -A 5 -n || true
  rg -n "NATIVE_APP_KEY" "$f" -A 2 -n || true
done

Length of output: 663


Manifest placeholder 설정 누락: NATIVE_APP_KEY

app/build.gradle.ktsdefaultConfigmanifestPlaceholders가 정의되어 있지 않아, ${NATIVE_APP_KEY}가 런타임에 치환되지 않고 그대로 남습니다. 아래 위치에 매핑을 추가해주세요.

• 수정 대상

  • 파일: app/build.gradle.kts
  • 섹션: android { defaultConfig { … } }

• 예시 스니펫 (Kotlin DSL)

android {
    defaultConfig {
        // 기존 buildConfigField는 그대로 유지
        buildConfigField("String", "NATIVE_APP_KEY", "\"${properties["NATIVE_APP_KEY"]}\"")

        // manifestPlaceholders 설정 추가
        manifestPlaceholders += mapOf(
            "NATIVE_APP_KEY" to properties["NATIVE_APP_KEY"] as String
        )
    }
}

위와 같이 설정하면 AndroidManifest.xml

<meta-data
    android:name="com.kakao.sdk.AppKey"
    android:value="${NATIVE_APP_KEY}" />

가 실제 앱 키로 정상 치환됩니다.

🤖 Prompt for AI Agents
In app/src/main/AndroidManifest.xml around lines 19-21 the meta-data value uses
${NATIVE_APP_KEY} but app/build.gradle.kts's android.defaultConfig is missing a
manifestPlaceholders entry so the placeholder isn't replaced at runtime; open
app/build.gradle.kts and inside android { defaultConfig { ... } } add a
manifestPlaceholders mapping that binds "NATIVE_APP_KEY" to your project
property (e.g., properties["NATIVE_APP_KEY"] as String), keeping any existing
buildConfigField entries intact so the manifest placeholder is properly
substituted at build time.


<activity
android:name="com.kakao.sdk.auth.AuthCodeHandlerActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />

<data android:host="oauth"
android:scheme="kakao${NATIVE_APP_KEY}" />

</intent-filter>
</activity>

<activity
android:name=".MainActivity"
android:exported="true"
Expand All @@ -27,5 +48,4 @@
</intent-filter>
</activity>
</application>

</manifest>
93 changes: 39 additions & 54 deletions app/src/main/java/com/texthip/thip/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,23 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.texthip.thip.ui.navigator.navigations.commonNavigation
import com.texthip.thip.ui.navigator.navigations.feedNavigation
import com.texthip.thip.ui.navigator.navigations.groupNavigation
import com.texthip.thip.ui.navigator.navigations.myPageNavigation
import com.texthip.thip.ui.navigator.navigations.searchNavigation
import com.texthip.thip.ui.navigator.routes.CommonRoutes
import com.texthip.thip.ui.signin.screen.LoginScreen
import com.texthip.thip.ui.signin.screen.SigninNicknameScreen
import com.texthip.thip.ui.signin.screen.SplashScreen
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.texthip.thip.data.manager.TokenManager
import com.texthip.thip.ui.theme.ThipTheme
import com.texthip.thip.ui.theme.ThipTheme.colors
import com.texthip.thip.ui.theme.ThipTheme.typography
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject

Expand All @@ -26,63 +34,40 @@ class MainActivity : ComponentActivity() {
enableEdgeToEdge()
setContent {
ThipTheme {
/*Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
name = "Android",
modifier = Modifier.padding(innerPadding)
)
}*/
MainScreen()
RootNavHost()
}
}
}
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Column {
Text(
text = "Hello $name!",
modifier = modifier,
style = typography.bigtitle_b700_s22_h24,
color = colors.Purple,
)

Text(
text = "Hello $name!",
modifier = modifier,
style = typography.smalltitle_sb600_s16_h20,
color = colors.NeonGreen,
)

Text(
text = "Hello $name!",
modifier = modifier,
style = typography.menu_sb600_s12,
color = colors.Red,
)
fun RootNavHost() {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = CommonRoutes.Splash
) {
// --- 인증 관련 화면들 ---
composable<CommonRoutes.Splash> {
SplashScreen(navController = navController)
}
composable<CommonRoutes.Login> {
LoginScreen(navController = navController)
}
composable<CommonRoutes.Signup> {
SigninNicknameScreen(navController = navController)
}

Text(
text = "Hello $name!",
modifier = modifier,
style = typography.navi_m500_s10,
color = colors.DarkGrey,
// --- 메인 관련 화면들 ---
feedNavigation(navController)
groupNavigation(
navController = navController,
navigateBack = navController::popBackStack
)

Text(
text = "Hello $name!",
modifier = modifier,
style = typography.view_r400_s11_h20,
color = colors.Black,
searchNavigation(navController)
myPageNavigation(navController)
commonNavigation(
navController = navController,
navigateBack = navController::popBackStack
)
}

}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
ThipTheme {
Greeting("Android")
}
}
16 changes: 15 additions & 1 deletion app/src/main/java/com/texthip/thip/ThipApplication.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
package com.texthip.thip

import com.kakao.sdk.common.KakaoSdk
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
import com.texthip.thip.BuildConfig


@HiltAndroidApp
class ThipApplication : Application()
class ThipApplication : Application(){
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

AndroidManifest에 Application 등록 및 Kakao 리디렉션 구성 확인 권장

@HiltAndroidApp를 사용하는 Application은 매니페스트 application android:name에 반드시 등록되어야 합니다. 또한 카카오 로그인 리디렉션을 위해 com.kakao.sdk.AppKey 메타데이터와 AuthCodeHandlerActivity 등록이 필요합니다. 로컬 환경/브랜치에 따라 누락되지 않았는지 한번 점검 부탁드립니다.

다음 스크립트로 매니페스트/빌드 설정을 빠르게 확인할 수 있습니다.


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "1) Application 클래스 등록 확인"
rg -n -C2 -P '<application[^>]*android:name\s*=\s*"(?:\.|com\.texthip\.thip\.)ThipApplication"' -g 'app/**/AndroidManifest.xml' || echo "⚠️ AndroidManifest에 ThipApplication 등록이 보이지 않습니다."

echo
echo "2) Kakao AppKey 메타데이터 확인"
rg -n -C2 -P '<meta-data[^>]*name="com\.kakao\.sdk\.AppKey"[^>]*/>' -g 'app/**/AndroidManifest.xml' || echo "⚠️ com.kakao.sdk.AppKey 메타데이터가 보이지 않습니다."

echo
echo "3) Kakao AuthCodeHandlerActivity 등록 확인"
rg -n -C2 -P 'com\.kakao\.sdk\.auth\.AuthCodeHandlerActivity' -g 'app/**/AndroidManifest.xml' || echo "⚠️ AuthCodeHandlerActivity 등록이 보이지 않습니다."

echo
echo "4) BuildConfig NATIVE_APP_KEY 정의 확인"
rg -n -C2 -P 'buildConfigField\([^)]*"String"\s*,\s*"NATIVE_APP_KEY"' -g 'app/**/build.gradle*' || echo "⚠️ build.gradle에 NATIVE_APP_KEY buildConfigField가 보이지 않습니다."

Length of output: 1692


AndroidManifest에 ThipApplication 및 Kakao AppKey 메타데이터 등록 필요

확인 결과, 아래 항목이 누락되어 있어 카카오 로그인 리디렉션이 정상 동작하지 않습니다. 적용 부탁드립니다.

• app/src/main/AndroidManifest.xml

  • <application> 태그에
    android:name=".ThipApplication"
    또는
    android:name="com.texthip.thip.ThipApplication"
    속성이 없습니다.
    • app/src/main/AndroidManifest.xml
  • <application> 내부에
    <meta-data
        android:name="com.kakao.sdk.AppKey"
        android:value="${NATIVE_APP_KEY}" />
    메타데이터 항목이 없습니다.
    • app/src/main/AndroidManifest.xml
  • AuthCodeHandlerActivity 등록은 올바르게 되어 있습니다.
    • app/build.gradle.kts
  • buildConfigField("String", "NATIVE_APP_KEY", …) 설정이 올바르게 되어 있습니다.

위 두 가지를 추가한 뒤 카카오 SDK 리디렉션이 정상 작동하는지 재확인 부탁드립니다.

🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/ThipApplication.kt around line 10,
add/update app/src/main/AndroidManifest.xml: set the <application> android:name
attribute to ".ThipApplication" or the full "com.texthip.thip.ThipApplication"
value, and inside <application> add the Kakao SDK meta-data element with
android:name="com.kakao.sdk.AppKey" and android:value="${NATIVE_APP_KEY}";
ensure app/build.gradle.kts already defines buildConfigField("String",
"NATIVE_APP_KEY", …) and then rebuild and verify Kakao login redirection works.

override fun onCreate() {
super.onCreate()

// 카카오 SDK 초기화
try {
KakaoSdk.init(this, BuildConfig.NATIVE_APP_KEY)
}catch (e: Exception){
e.printStackTrace()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.texthip.thip.data.di

import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import com.texthip.thip.BuildConfig
import com.texthip.thip.data.service.AuthService
import com.texthip.thip.utils.auth.AuthInterceptor
import dagger.Module
import dagger.Provides
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/java/com/texthip/thip/data/di/ServiceModule.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.texthip.thip.data.di

import com.texthip.thip.data.service.AuthService
import com.texthip.thip.data.service.BookService
import com.texthip.thip.data.service.RecentSearchService
import com.texthip.thip.data.service.CommentsService
Expand All @@ -22,11 +23,18 @@ object ServiceModule {
fun provideBookService(retrofit: Retrofit): BookService {
return retrofit.create(BookService::class.java)
}

@Provides
@Singleton
fun providesRoomsService(retrofit: Retrofit): RoomsService =
retrofit.create(RoomsService::class.java)

@Provides
@Singleton
fun provideAuthService(retrofit: Retrofit): AuthService {
return retrofit.create(AuthService::class.java)
}

@Provides
@Singleton
fun provideUserService(retrofit: Retrofit): UserService {
Expand Down
28 changes: 27 additions & 1 deletion app/src/main/java/com/texthip/thip/data/manager/TokenManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,44 @@ import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import javax.inject.Singleton


private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "thip_tokens")

@Singleton
class TokenManager @Inject constructor(
@ApplicationContext private val context: Context
) {
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "thip_auth_tokens")

Comment on lines +22 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Context.dataStore를 클래스 내부에서 다시 정의하면 DataStore 인스턴스가 이중으로 생성될 수 있습니다. 하나로 통일하세요.

동일 파일에

  • 파일 상단(top-level) Context.dataStore (name = "thip_tokens")
  • 클래스 내부 멤버 확장 Context.dataStore (name = "thip_auth_tokens")

가 동시에 존재합니다. 호출 위치에 따라 서로 다른 파일명으로 분리된 두 개의 DataStore를 사용할 위험이 있습니다. 토큰 저장/조회가 서로 다른 저장소를 바라보면 데이터 유실·불일치가 발생합니다.

권장: 클래스 내부 정의를 제거하고, top-level 하나만 남기되 파일명을 원하는 최종값(예: "thip_auth_tokens")으로 맞추세요.

적용 diff(선택 범위 내 제거):

-    private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "thip_auth_tokens")

선택 범위 밖(참고): top-level 정의를 다음과 같이 통일하세요.

// line 16 제안
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "thip_auth_tokens")
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/data/manager/TokenManager.kt around lines
22-23, there are two Context.dataStore declarations (a top-level one named
"thip_tokens" and a class-internal one named "thip_auth_tokens") which can
create two separate DataStore instances; remove the class-internal
Context.dataStore declaration so only the top-level extension remains, and
ensure the top-level preferencesDataStore uses the final filename
"thip_auth_tokens" (update its name if needed) so all token reads/writes use the
single unified DataStore.

companion object {
//토큰저장에 사용되는 키
private val APP_TOKEN_KEY = stringPreferencesKey("app_token")
}
Comment on lines +24 to +27
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

companion object가 중복 선언되어 컴파일 오류가 납니다. 키 정의를 하나의 companion으로 통합하세요.

현재 클래스 아래쪽(라인 49-53)에 또 다른 companion object가 존재합니다. Kotlin은 클래스 당 하나의 companion만 허용합니다. 또한 키가 두 곳으로 분산되면 유지보수성이 떨어집니다.

한 곳으로 합치고, 아래쪽의 중복 companion은 제거하세요.

적용 diff(상단 companion에 모든 키 통합, 하단 중복 companion 제거는 다음 코멘트 설명 참고):

-    companion object {
-        //토큰저장에 사용되는 키
-        private val APP_TOKEN_KEY = stringPreferencesKey("app_token")
-    }
+    companion object {
+        // Preferences Keys
+        private val APP_TOKEN_KEY = stringPreferencesKey("app_token")
+        private val TEMP_TOKEN_KEY = stringPreferencesKey("temp_token")
+        private val ACCESS_TOKEN_KEY = stringPreferencesKey("access_token")
+        private val REFRESH_TOKEN_KEY = stringPreferencesKey("refresh_token")
+    }

선택 범위 밖(설명): 라인 49-53의 하단 companion object 블록은 통째로 삭제하세요.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
companion object {
//토큰저장에 사용되는 키
private val APP_TOKEN_KEY = stringPreferencesKey("app_token")
}
companion object {
// Preferences Keys
private val APP_TOKEN_KEY = stringPreferencesKey("app_token")
private val TEMP_TOKEN_KEY = stringPreferencesKey("temp_token")
private val ACCESS_TOKEN_KEY = stringPreferencesKey("access_token")
private val REFRESH_TOKEN_KEY= stringPreferencesKey("refresh_token")
}
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/data/manager/TokenManager.kt around lines
24-27 and 49-53, there are two companion object declarations causing a compile
error; merge the key definitions into the top companion by moving any keys from
the bottom companion into the existing companion object at lines ~24-27 (e.g.,
consolidate stringPreferencesKey("app_token") and any other keys into that
single companion) and then delete the entire lower companion object block (lines
~49-53) so the class contains only one companion with all token-related keys.


//토큰 저장
suspend fun saveToken(token: String) {
context.dataStore.edit { prefs ->
prefs[APP_TOKEN_KEY] = token
}
}

//저장된 토큰을 Flow 형태로 불러옴
fun getToken(): Flow<String?> {
return context.dataStore.data.map { prefs ->
prefs[APP_TOKEN_KEY]
}
}
Comment on lines +36 to +41
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

DataStore 스트림 예외 대비 로직을 추가하세요.

dataStore.data는 IOException 등으로 실패 시 예외를 던질 수 있습니다. 토큰 조회 스트림에 catch {}를 추가해 앱 크래시를 방지하세요.

적용 diff(선택된 범위 내 변경):

-    fun getToken(): Flow<String?> {
-        return context.dataStore.data.map { prefs ->
-            prefs[APP_TOKEN_KEY]
-        }
-    }
+    fun getToken(): Flow<String?> {
+        return context.dataStore.data
+            .catch { emit(emptyPreferences()) }
+            .map { prefs ->
+                prefs[APP_TOKEN_KEY]
+            }
+    }

선택 범위 외 필요한 import:

import kotlinx.coroutines.flow.catch
import androidx.datastore.preferences.core.emptyPreferences
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/data/manager/TokenManager.kt around lines
33 to 38, the Flow returned from context.dataStore.data can throw (e.g.
IOException) and currently has no error handling; wrap the dataStore.data stream
with .catch { if (it is IOException) emit(emptyPreferences()) else throw it } so
the stream recovers by emitting emptyPreferences() instead of crashing, then
continue to map prefs[APP_TOKEN_KEY]; also add the recommended imports:
kotlinx.coroutines.flow.catch and
androidx.datastore.preferences.core.emptyPreferences.


//저장된 토큰 삭제 (로그아웃 시?)
suspend fun deleteToken() {
context.dataStore.edit { prefs ->
prefs.remove(APP_TOKEN_KEY)
Comment on lines +43 to +46
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

중괄호 누락으로 컴파일 오류 발생 — deleteToken 블록을 닫아주세요.

edit {} 람다와 함수의 닫는 중괄호가 없습니다.

적용 diff:

     suspend fun deleteToken() {
         context.dataStore.edit { prefs ->
             prefs.remove(APP_TOKEN_KEY)
+        }
+    }

추가 제안: 본 메서드는 APP_TOKEN만 지우고, 아래의 clearTokens()는 전체 삭제를 수행합니다. 로그아웃 정책에 따라 둘 중 하나로 일원화하거나, 메서드명을 deleteAppToken() 등으로 명확히 구분하는 것을 권장합니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
//저장된 토큰 삭제 (로그아웃 시?)
suspend fun deleteToken() {
context.dataStore.edit { prefs ->
prefs.remove(APP_TOKEN_KEY)
//저장된 토큰 삭제 (로그아웃 시?)
suspend fun deleteToken() {
context.dataStore.edit { prefs ->
prefs.remove(APP_TOKEN_KEY)
}
}
🤖 Prompt for AI Agents
In app/src/main/java/com/texthip/thip/data/manager/TokenManager.kt around lines
43 to 46, the deleteToken() function is missing closing braces for the
dataStore.edit { ... } lambda and the function itself, causing a compile error;
add the two missing closing braces to properly close the edit lambda and the
function, and (optionally) rename the method to deleteAppToken() or consolidate
with clearTokens() depending on logout semantics to avoid ambiguity.


// 저장할 데이터의 Key 정의
companion object {
private val TEMP_TOKEN_KEY = stringPreferencesKey("temp_token")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.texthip.thip.data.model.auth.request
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class AuthRequest(
@SerialName("oauth2Id") val oauth2Id: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.texthip.thip.data.model.auth.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class AuthResponse(
@SerialName("token") val token: String,
@SerialName("isNewUser") val isNewUser: Boolean
)
Loading