Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@
"backgroundColor": "#6C5CE7"
},
"intentFilters": [
{
"action": "VIEW",
"data": [
{
"scheme": "intelfit",
"host": "*",
"pathPrefix": "/auth/kakao"
}
],
"category": ["BROWSABLE", "DEFAULT"]
},
{
"action": "VIEW",
"data": [

Choose a reason for hiding this comment

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

주석을 통해 변경 사항에 대한 설명이 부족합니다. 이번 변경은 새로운 인텐트 필터를 추가하는 것으로 보이는데, 이로 인해 앱의 동작이나 보안에 문제가 생길 수 있습니다.

  1. Wildcard Host 사용의 위험: host에 '*'를 사용하는 것은 모든 호스트에서 해당 URL을 수용할 수 있도록 합니다. 이는 보안 위험을 초래할 수 있으며, 특정 호스트만 허용하는 것이 좋습니다.
  2. pathPrefix의 호환성 검토: /auth/kakao 경로가 올바르게 작동하는지 확인해야 합니다. 다른 경로와 충돌이 발생하지 않도록 관리해야 합니다.
  3. 인텐트 필터에 대한 주석 추가: 이 변경 사항이 무엇을 목적으로 하는지, 어떤 기능을 추가하는지에 대한 설명이 필요합니다. 이렇게 하면 코드 유지보수와 문서화에 도움이 됩니다.
  4. 테스트 필요: 이 인텐트 필터가 정상적으로 작동하는지, 앱 전반의 기능에 영향을 주지 않는지 철저하게 테스트해야 합니다.

이러한 점들 때문에 현재 상태에서는 머지하기에 적합하지 않습니다. 추가적인 리뷰와 테스트가 필요합니다.

Expand Down
93 changes: 57 additions & 36 deletions src/screens/auth/KakaoOnboardingScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Alert,
ActivityIndicator,
Modal,
SafeAreaView,
} from "react-native";
import { Picker } from "@react-native-picker/picker";
import { authAPI } from "../../services";
Expand Down Expand Up @@ -43,6 +44,15 @@ const experienceLevelOptions = [
{ label: "고급자", value: "ADVANCED" },
];

const healthConcernOptions = [
{ label: "의지 부족", value: "WILLPOWER" },
{ label: "근육의 자극", value: "MUSCLE_STIMULATION" },
{ label: "루틴 짜기 어려움", value: "ROUTINE_DIFFICULTY" },
{ label: "올바른 운동 자세", value: "CORRECT_FORM" },
{ label: "식단 관리", value: "DIET_MANAGEMENT" },
{ label: "기타", value: "OTHER" },
];

const KakaoOnboardingScreen = ({ navigation }: any) => {
const [loading, setLoading] = useState(false);
const [formData, setFormData] = useState({
Expand Down Expand Up @@ -70,6 +80,7 @@ const KakaoOnboardingScreen = ({ navigation }: any) => {
const [healthGoalModalVisible, setHealthGoalModalVisible] = useState(false);
const [experienceLevelModalVisible, setExperienceLevelModalVisible] =
useState(false);
const [healthConcernModalVisible, setHealthConcernModalVisible] = useState(false);

const handleChange = (name: string, value: string) => {
setFormData((prev) => ({ ...prev, [name]: value }));
Expand Down Expand Up @@ -205,11 +216,15 @@ const KakaoOnboardingScreen = ({ navigation }: any) => {
};

return (
<KeyboardAvoidingView
style={styles.container}
behavior={Platform.OS === "ios" ? "padding" : "height"}
>
<ScrollView contentContainerStyle={styles.scrollContent}>
<SafeAreaView style={styles.container}>
<KeyboardAvoidingView
style={styles.keyboardView}
behavior={Platform.OS === "ios" ? "padding" : "height"}
>
<ScrollView
contentContainerStyle={styles.scrollContent}
showsVerticalScrollIndicator={false}
>
<View style={styles.header}>
<Text style={styles.title}>신체정보를 입력해주세요</Text>
<Text style={styles.subtitle}>
Expand Down Expand Up @@ -318,12 +333,14 @@ const KakaoOnboardingScreen = ({ navigation }: any) => {
}}
style={styles.modalPicker}
itemStyle={styles.pickerItemStyle}
dropdownIconColor="#ffffff"
>
{generateYearOptions().map((year) => (
<Picker.Item
key={year}
label={String(year)}
value={String(year)}
color={Platform.OS === "android" ? "#ffffff" : undefined}
/>
))}
</Picker>
Expand All @@ -349,12 +366,14 @@ const KakaoOnboardingScreen = ({ navigation }: any) => {
}}
style={styles.modalPicker}
itemStyle={styles.pickerItemStyle}
dropdownIconColor="#ffffff"
>
{generateMonthOptions().map((month) => (
<Picker.Item
key={month}
label={String(month).padStart(2, "0")}
value={String(month)}
color={Platform.OS === "android" ? "#ffffff" : undefined}
/>
))}
</Picker>
Expand All @@ -368,6 +387,7 @@ const KakaoOnboardingScreen = ({ navigation }: any) => {
}}
style={styles.modalPicker}
itemStyle={styles.pickerItemStyle}
dropdownIconColor="#ffffff"
>
{(() => {
if (tempPickerValue.year && tempPickerValue.month) {
Expand Down Expand Up @@ -401,6 +421,7 @@ const KakaoOnboardingScreen = ({ navigation }: any) => {
key={day}
label={String(day).padStart(2, "0")}
value={String(day)}
color={Platform.OS === "android" ? "#ffffff" : undefined}
/>
))}
</Picker>
Expand Down Expand Up @@ -727,41 +748,41 @@ const KakaoOnboardingScreen = ({ navigation }: any) => {
</TouchableOpacity>
</Modal>

{/* 운동 경험 수준 (선택) */}
{/* 헬스 고민 (선택) */}
<View style={styles.inputGroup}>
<TouchableOpacity
activeOpacity={0.8}
style={styles.birthDateButtonContainer}
onPress={() => setExperienceLevelModalVisible(true)}
onPress={() => setHealthConcernModalVisible(true)}
>
<TextInput
style={styles.input}
value={
formData.experienceLevel
? experienceLevelOptions.find(
(opt) => opt.value === formData.experienceLevel
formData.fitnessConcerns
? healthConcernOptions.find(
(opt) => opt.value === formData.fitnessConcerns
)?.label || ""
: ""
}
placeholder="운동 경험 수준 (선택)"
placeholder="헬스 고민"
placeholderTextColor="rgba(255, 255, 255, 0.7)"
editable={false}
pointerEvents="none"
/>
</TouchableOpacity>
</View>

{/* 운동 경험 수준 선택 모달 */}
{/* 헬스 고민 선택 모달 */}
<Modal
visible={experienceLevelModalVisible}
visible={healthConcernModalVisible}
transparent={true}
animationType="slide"
onRequestClose={() => setExperienceLevelModalVisible(false)}
onRequestClose={() => setHealthConcernModalVisible(false)}
>
<TouchableOpacity
style={styles.modalOverlay}
activeOpacity={1}
onPress={() => setExperienceLevelModalVisible(false)}
onPress={() => setHealthConcernModalVisible(false)}
>
<TouchableOpacity
activeOpacity={1}
Expand All @@ -770,32 +791,32 @@ const KakaoOnboardingScreen = ({ navigation }: any) => {
>
<View style={styles.modalHeader}>
<TouchableOpacity
onPress={() => setExperienceLevelModalVisible(false)}
onPress={() => setHealthConcernModalVisible(false)}
>
<Text style={styles.modalCancelText}>취소</Text>
</TouchableOpacity>
<Text style={styles.modalTitle}>운동 경험 수준 선택</Text>
<Text style={styles.modalTitle}>헬스 고민 선택</Text>
<View style={{ width: 50 }} />
</View>
<View style={styles.modalOptionContainer}>
<View style={styles.optionGrid}>
{experienceLevelOptions.map((option) => (
{healthConcernOptions.map((option) => (
<TouchableOpacity
key={option.value}
style={[
styles.optionButton,
formData.experienceLevel === option.value &&
formData.fitnessConcerns === option.value &&
styles.optionButtonSelected,
]}
onPress={() => {
handleChange("experienceLevel", option.value);
setExperienceLevelModalVisible(false);
handleChange("fitnessConcerns", option.value);
setHealthConcernModalVisible(false);
}}
>
<Text
style={[
styles.optionButtonText,
formData.experienceLevel === option.value &&
formData.fitnessConcerns === option.value &&
styles.optionButtonTextSelected,
]}
>
Expand All @@ -808,18 +829,6 @@ const KakaoOnboardingScreen = ({ navigation }: any) => {
</TouchableOpacity>
</TouchableOpacity>
</Modal>

{/* 헬스 고민 (선택) */}
<View style={styles.inputGroup}>
<TextInput
style={styles.input}
placeholder="헬스 고민 (선택)"
value={formData.fitnessConcerns}
onChangeText={(text) => handleChange("fitnessConcerns", text)}
placeholderTextColor="rgba(255, 255, 255, 0.7)"
multiline
/>
</View>
</View>

<TouchableOpacity
Expand All @@ -834,7 +843,8 @@ const KakaoOnboardingScreen = ({ navigation }: any) => {
)}
</TouchableOpacity>
</ScrollView>
</KeyboardAvoidingView>
</KeyboardAvoidingView>
</SafeAreaView>
);
};

Expand All @@ -843,10 +853,13 @@ const styles = StyleSheet.create({
flex: 1,
backgroundColor: "#252525",
},
keyboardView: {
flex: 1,
},
scrollContent: {
flexGrow: 1,
paddingHorizontal: 20,
paddingTop: 60,
paddingTop: Platform.OS === "ios" ? 20 : 40,
paddingBottom: 40,
},
header: {
Expand Down Expand Up @@ -886,6 +899,11 @@ const styles = StyleSheet.create({
fontWeight: "400",
color: "#ffffff",
},
textAreaInput: {
height: 120,
paddingTop: 16,
paddingBottom: 16,
},
birthDateButtonContainer: {
width: "100%",
},
Expand Down Expand Up @@ -962,9 +980,12 @@ const styles = StyleSheet.create({
modalPicker: {
width: "100%",
height: 150,
backgroundColor: "#252525",
},
pickerItemStyle: {
color: "#ffffff",
fontSize: 18,
fontWeight: "400",
},
genderOptionContainer: {
paddingHorizontal: 20,

Choose a reason for hiding this comment

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

코드 리뷰

  1. 안정성: handleChange 함수는 namevalue를 기반으로 상태를 업데이트합니다. 코드 전반에 걸쳐 이 함수가 호출되는 것을 확인했지만, 각 상태값이 코드 내에서 올바르게 정의되어 있는지, { formData.fitnessConcerns }을 포함한 상태의 초기값이 확인되지 않았습니다. 특히, experienceLevel과 같은 기존 프로퍼티 하드 코딩이 없도록 주의해야 합니다.

  2. 시맨틱 구조: SafeAreaViewKeyboardAvoidingView를 올바르게 조합하여 뷰의 안전 영역을 처리하는 것은 좋지만, KeyboardAvoidingViewSafeAreaView 안에 포함시키는 것이 기능적으로 더 나은지 검토할 필요가 있습니다. iOS에서 잘 동작하는지 확인이 필요합니다.

  3. UI 피드백: 사용자가 분석하여 선택할 수 있는 옵션을 모두 보여주고 UI의 일관성을 유지하는 것이 매우 중요합니다. 각 Picker와 Modal이 어떻게 상호작용하는지, 특히 헬스 고민 선택과 관련된 UI 변경에서 의도된 사용자인지에 대한 피드백이 필요합니다.

  4. 접근성: TouchableOpacity 안에 텍스트가 들어 있기 때문에 사용자에게 어떤 액션이 가능하다는 것을 알리는 시각적인 요소 또는 스포트라이트가 필요합니다. 접근성과 사용자 경험을 개선하기 위해 Accessible 속성을 활용하는 것도 고려해보세요.

  5. 모듈화 및 유지 보수: 신규 추가된 healthConcernOptions와 같은 항목들이 있다면, 이러한 값을 정의하는 구조체를 외부 파일로 분리하여 코드 재사용성을 높이는 것이 좋습니다. 여러 곳에서 공통적으로 사용될 수 있기 때문입니다.

이러한 점들을 감안할 때, 현재 코드 패치는 반영 및 개선이 필요해 보입니다.

Expand Down
Loading