인프런 커뮤니티 질문&답변
댓글 버튼 하단에 고정되지 않는 이슈
작성
·
3
·
수정됨
0

node 버전 : v24.11.1
[id.tsx] 파일입니다. 현재 상세 페이지를 가면 아래와 같이 댓글 버튼이 상단으로 올라오는 현상이 생겼습니다. 또한 답글 남기기를 눌러도 focus는 댓글 input으로 되지만, 화면처럼 스크롤이 내려가는 현상은 안나타납니다.
npx expo start를 이용하여, 실기기로 테스트한겁니다!
import AuthRoute from "@/components/AuthRoute";
import CommentItem from "@/components/CommentItem";
import FeedItem from "@/components/FeedItem";
import InputField from "@/components/InputField";
import { colors } from "@/constants";
import useCreateComment from "@/hooks/queries/useCreateComment";
import useGetPost from "@/hooks/queries/useGetPost";
import useKeyboard from "@/hooks/useKeyboard";
import { useLocalSearchParams } from "expo-router";
import { Fragment, useRef, useState } from "react";
import {
Keyboard,
KeyboardAvoidingView,
Platform,
Pressable,
ScrollView,
StyleSheet,
Text,
TextInput,
View,
} from "react-native";
import {
SafeAreaView,
useSafeAreaInsets,
} from "react-native-safe-area-context";
export default function PostDetailScreen() {
const { id } = useLocalSearchParams();
const { data: post, isPending, isError } = useGetPost(Number(id));
const createComment = useCreateComment();
const [content, setContent] = useState("");
const scrollRef = useRef<ScrollView | null>(null);
const inputRef = useRef<TextInput | null>(null);
const [parentCommentId, setParentCommentId] = useState<number | null>(null);
const { isKeyboardVisible } = useKeyboard();
const insets = useSafeAreaInsets();
if (isPending || isError) {
return <></>;
}
const handleReply = (commentId: number) => {
setParentCommentId(commentId);
inputRef.current?.focus();
};
const handleCancelReply = () => {
setParentCommentId(null);
Keyboard.dismiss();
};
const handleSubmitComment = () => {
const commentData = {
postId: post.id,
content: content,
};
if (parentCommentId) {
createComment.mutate({ ...commentData, parentCommentId });
setContent("");
handleCancelReply();
return;
}
if (parentCommentId) {
createComment.mutate({ ...commentData, parentCommentId });
setContent("");
handleCancelReply();
return;
}
createComment.mutate(commentData);
setContent("");
setTimeout(() => {
scrollRef.current?.scrollToEnd();
}, 500);
};
return (
<AuthRoute>
<SafeAreaView
style={styles.container}
edges={["right", "left", "bottom"]}
>
<KeyboardAvoidingView
contentContainerStyle={styles.awareScrollViewContainer}
behavior="height"
keyboardVerticalOffset={
Platform.OS === "ios" || isKeyboardVisible ? 100 : insets.bottom
}
>
<ScrollView
ref={scrollRef}
style={{ marginBottom: 75 }}
contentContainerStyle={styles.scrollViewContainer}
>
<View style={{ marginTop: 12 }}>
<FeedItem post={post} isDetail />
<Text style={styles.commentCount}>
댓글 {post.commentCount}개
</Text>
</View>
{post.comments?.map((comment) => (
<Fragment key={comment.id}>
<CommentItem
parentCommentId={parentCommentId}
onReply={() => handleReply(comment.id)}
onCancelReply={handleCancelReply}
comment={comment}
/>
{comment.replies.map((reply) => (
<CommentItem key={reply.id} comment={reply} isReply />
))}
</Fragment>
))}
</ScrollView>
<View style={styles.commentInputContainer}>
<InputField
ref={inputRef}
value={content}
returnKeyType="send"
onSubmitEditing={handleSubmitComment}
onChangeText={(text) => setContent(text)}
placeholder={
parentCommentId ? "답글 남기는중..." : "댓글을 남겨보세요."
}
rightChild={
<Pressable
disabled={!content}
style={styles.inputButtonContainer}
onPress={handleSubmitComment}
>
<Text style={styles.inputButtonText}>등록</Text>
</Pressable>
}
/>
</View>
</KeyboardAvoidingView>
</SafeAreaView>
</AuthRoute>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: colors.WHITE,
},
awareScrollViewContainer: {
flex: 1,
backgroundColor: colors.GRAY_200,
},
scrollViewContainer: {
backgroundColor: colors.GRAY_200,
},
commentCount: {
marginTop: 12,
backgroundColor: colors.WHITE,
paddingVertical: 12,
paddingHorizontal: 16,
fontSize: 16,
fontWeight: "bold",
},
commentInputContainer: {
width: "100%",
borderTopColor: colors.GRAY_200,
borderTopWidth: StyleSheet.hairlineWidth,
backgroundColor: colors.WHITE,
padding: 16,
bottom: 0,
position: "absolute",
},
inputButtonContainer: {
backgroundColor: colors.ORANGE_600,
padding: 8,
borderRadius: 5,
},
inputButtonText: {
color: colors.WHITE,
fontWeight: "bold",
},
});
답변 1
0
안녕하세요, 인프런 AI 인턴입니다. nubes님.
게시물 상세 페이지에서 댓글 입력란이 하단에 고정되지 않는 문제에 대해서는 몇 가지 확인해야 할 요소가 있습니다. 이와 유사한 케이스에서 발생 가능한 이슈를 정리해 드리겠습니다.
주요 원인
KeyboardAvoidance 이슈:
KeyboardAvoidingView는 기본적으로 iOS와 Android에서 키보드가 등장할 때 View의 위치 조정에 차이를 보일 수 있습니다. 이때behavior속성과keyboardVerticalOffset속성이 올바르게 설정되어야 합니다.Scroll 관련 문제: ScrollView가 잘못된 마진이나 패딩을 가질 경우, 댓글란이 상단으로 올라가는 현상이 발생할 수 있습니다.
뷰 계층 구조:
KeyboardAvoidingView와ScrollView, 그리고 댓글 입력란 사이의 뷰 계층 구조가 올바른지 확인해 보는 것이 좋습니다.
해결 방법
- KeyboardAvoidingView Props 확인
behavior를padding으로 설정해볼 수 있습니다. iOS에서는padding이height보다 더욱 효과적으로 작동할 수 있습니다.
<KeyboardAvoidingView
contentContainerStyle={styles.awareScrollViewContainer}
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
keyboardVerticalOffset={Platform.OS === "ios" ? 100 : insets.bottom}
>
ScrollView 속성 점검
- ScrollView의
contentContainerStyle나style에 여백(margin/padding)가 설정되어 있는 경우 스크롤 동작 문제가 발생할 수 있습니다.
- 댓글 입력란의
position속성을fixed대신absolute로 설정하고,bottom: 0와width: "100%"를 유지한 상태에서 위치가 고정되도록 설정합니다.
- ScrollView의
React Native Debugging
- 스타일링과 관련 있는 문제는
react-native의 디버깅 툴을 사용해 스크린에 나타나는 레이아웃을 직접 시각화하며 해결할 수 있습니다.
- 스타일링과 관련 있는 문제는
참고할 만한 커뮤니티 대화
이와 유사한 상황에서의 문제 해결 과정을 공유하는 여러 개발자들이 있습니다. React Native Documentation을 참조하여 다양한 접근 방식과 옵션을 실험해 보세요.
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 사이트를 추천해드리고 있습니다.
현재 베타 기능으로 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏 추가적으로 궁금하신 점 있으면 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.





