diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index be87848..4ccc396 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,17 +1,2 @@
-# Organizer
-* @kjoon418 @junseok0304
-
-# Backend
-* @jihoo2002 @bomin0214 @TwooTwoo @ggok0265
-
-# Web
-* @ten0213
-
# Mobile
* @Han6262
-
-# PM
-* @iamseoyoung @tto-oy
-
-# Design
-* @hyeonji44
diff --git a/.github/auto_assign.yml b/.github/auto_assign.yml
index 7c96020..dbd3a4a 100644
--- a/.github/auto_assign.yml
+++ b/.github/auto_assign.yml
@@ -1,2 +1,19 @@
-addReviewers: false
-addAssignees: author
\ No newline at end of file
+# Set to true to add reviewers to pull requests
+addReviewers: true
+
+# Set to true to add assignees to pull requests
+addAssignees: true
+
+# A list of reviewers to be added to pull requests (GitHub user name)
+reviewers:
+ - reviewerA
+ - reviewerB
+ - reviewerC
+
+# A list of keywords to be skipped the process that add reviewers if pull requests include it
+skipKeywords:
+ - wip
+
+# A number of reviewers added to the pull request
+# Set 0 to add all the reviewers (default: 0)
+numberOfReviewers: 0
\ No newline at end of file
diff --git a/App.js b/App.js
new file mode 100644
index 0000000..db78f17
--- /dev/null
+++ b/App.js
@@ -0,0 +1,3 @@
+import App from "./src/App";
+
+export default App;
\ No newline at end of file
diff --git a/assets/adaptive-icon.png b/assets/adaptive-icon.png
new file mode 100644
index 0000000..03d6f6b
Binary files /dev/null and b/assets/adaptive-icon.png differ
diff --git a/assets/favicon.png b/assets/favicon.png
new file mode 100644
index 0000000..e75f697
Binary files /dev/null and b/assets/favicon.png differ
diff --git a/assets/icon.png b/assets/icon.png
new file mode 100644
index 0000000..a0b1526
Binary files /dev/null and b/assets/icon.png differ
diff --git a/assets/logo.png b/assets/logo.png
new file mode 100644
index 0000000..1b14e03
Binary files /dev/null and b/assets/logo.png differ
diff --git a/assets/splash-icon.png b/assets/splash-icon.png
new file mode 100644
index 0000000..03d6f6b
Binary files /dev/null and b/assets/splash-icon.png differ
diff --git a/src/App.js b/src/App.js
new file mode 100644
index 0000000..3be6d8f
--- /dev/null
+++ b/src/App.js
@@ -0,0 +1,22 @@
+import React from "react";
+import { StyleSheet, View } from "react-native";
+import { NavigationContainer } from "@react-navigation/native";
+import AuthStack from "../src/navigaitons/AuthStack";
+import { UserProvider } from "./context/UserContext";
+
+export default function App() {
+ return (
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: "#fff",
+ },
+});
diff --git a/src/api/auth.js b/src/api/auth.js
new file mode 100644
index 0000000..2748f01
--- /dev/null
+++ b/src/api/auth.js
@@ -0,0 +1,11 @@
+export const signInAsync = (email, password) => {
+ return new Promise((resolve, reject) => {
+ setTimeout(() => {
+ if (email === "dlwns1221@gmail.com" && password === "qlalfqjsgh") {
+ resolve({ id: "u1", name: "어드민", email });
+ } else {
+ reject(new Error("INVALID_CREDENTIALS"));
+ }
+ }, 1000);
+ });
+};
diff --git a/src/componets/Button.js b/src/componets/Button.js
new file mode 100644
index 0000000..bd7e28a
--- /dev/null
+++ b/src/componets/Button.js
@@ -0,0 +1,40 @@
+import React from "react";
+import { Pressable, Text, StyleSheet } from "react-native";
+import PropTypes from "prop-types";
+
+export default function Button({ title, onPress, disabled }) {
+ return (
+
+ {title}
+
+ );
+}
+
+Button.propTypes = {
+ title: PropTypes.string.isRequired,
+ onPress: PropTypes.func,
+ disabled: PropTypes.bool,
+};
+
+const styles = StyleSheet.create({
+ button: {
+ width: "100%",
+ height: 48,
+ borderRadius: 10,
+ justifyContent: "center",
+ alignItems: "center",
+ marginTop: 28,
+ },
+ text: {
+ fontSize: 15,
+ fontWeight: "600",
+ color: "#ffffff",
+ },
+});
diff --git a/src/componets/Input.js b/src/componets/Input.js
new file mode 100644
index 0000000..6e57b96
--- /dev/null
+++ b/src/componets/Input.js
@@ -0,0 +1,73 @@
+import React, { useState } from "react";
+import { View, Text, TextInput, StyleSheet } from "react-native";
+import PropTypes from "prop-types";
+import { MaterialIcons } from "@expo/vector-icons";
+
+export const KeyboardTypes = {
+ DEFAULT: "default",
+ EMAIL: "email-address",
+};
+
+function Input({ title, placeholder, keyboardType , secureTextEntry, iconName, value, onChangeText }) {
+ const [isFocused, setIsFocused] = useState(false);
+ return (
+
+ {!!title && {title}}
+
+
+ setIsFocused(true)}
+ onBlur={() => setIsFocused(false)}
+ />
+
+
+ );
+}
+
+Input.propTypes = {
+ title: PropTypes.string.isRequired,
+ placeholder: PropTypes.string,
+ iconName: PropTypes.string,
+ value : PropTypes.string,
+ onChangeText : PropTypes.func,
+};
+
+export default Input;
+
+const styles = StyleSheet.create({
+ container: {
+ width: "100%",
+},
+ title: {
+ fontSize: 14,
+ color: "#7b7171ff",
+ marginTop: 20,
+ marginBottom: 5,
+},
+ input: {
+ flex: 1,
+ color: "black",
+ },
+ wrap: {
+ width: "100%",
+ height: 49,
+ borderWidth: 1,
+ borderRadius: 7,
+ borderColor: "#2F6BFF",
+ flexDirection: "row",
+ alignItems: "center",
+ paddingHorizontal: 10,
+ },
+ icon: {
+ marginRight: 5,
+ },
+});
\ No newline at end of file
diff --git a/src/context/UserContext.js b/src/context/UserContext.js
new file mode 100644
index 0000000..4cd7311
--- /dev/null
+++ b/src/context/UserContext.js
@@ -0,0 +1,13 @@
+import React, { createContext, useState } from "react";
+
+export const UserContext = createContext();
+
+export function UserProvider({ children }) {
+ const [user, setUser] = useState(null);
+
+ return (
+
+ {children}
+
+ );
+}
diff --git a/src/navigaitons/AuthStack.js b/src/navigaitons/AuthStack.js
new file mode 100644
index 0000000..e8663d7
--- /dev/null
+++ b/src/navigaitons/AuthStack.js
@@ -0,0 +1,35 @@
+import React from "react";
+import { createNativeStackNavigator } from "@react-navigation/native-stack";
+import SignInScreen from "../screens/SignInScreen";
+import ListScreen from "../screens/ListScreen";
+
+const Stack = createNativeStackNavigator();
+
+const AuthStack = () => {
+ return (
+
+
+
+
+ );
+};
+
+export default AuthStack;
diff --git a/src/screens/ListScreen.js b/src/screens/ListScreen.js
new file mode 100644
index 0000000..a4f53b0
--- /dev/null
+++ b/src/screens/ListScreen.js
@@ -0,0 +1,67 @@
+import React, { useContext, useState, memo } from "react";
+import { View, Text, FlatList, Pressable, StyleSheet } from "react-native";
+import { UserContext } from "../context/UserContext";
+
+export default function ListScreen() {
+ const { user } = useContext(UserContext);
+ const [todos, setTodos] = useState([
+ { id: 1, text: "잠자기", done: false },
+ { id: 2, text: "밥먹기", done: false },
+ { id: 3, text: "GDG 과제하기..", done: true},
+ ]);
+
+ const toggle = (id) => {
+ setTodos((prev) =>
+ prev.map((t) => (t.id === id ? { ...t, done: !t.done } : t))
+ );
+ };
+
+ const remove = (id) => {
+ setTodos((prev) => prev.filter((t) => t.id !== id));
+ };
+
+ const TodoItem = memo(({ item }) => (
+
+ toggle(item.id)}>
+ {item.done ? "O" : "X"} {/*체크 아이콘 나중에 수정할 예정*/}
+
+
+
+ {item.text}
+
+
+ remove(item.id)}>
+ 쓰레기통 {/*스레기통 아이콘 나중에 수정할 예정*/}
+
+
+ ));
+
+ return (
+
+ 리스트 페이지
+
+
+ {user ? `로그인: ${user.email}` : "로그인 정보 없음"}
+
+
+ item.id.toString()}
+ renderItem={({ item }) => }
+ ListEmptyComponent={할 일을 추가해주세요}
+ />
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: { flex: 1, paddingTop: 50, paddingHorizontal: 20 },
+ title: { fontSize: 22, fontWeight: "bold", marginBottom: 10 },
+ user: { marginBottom: 20, fontSize: 14 },
+ row: { flexDirection: "row", alignItems: "center", paddingVertical: 10 },
+ check: { fontSize: 24, marginRight: 10 },
+ text: { flex: 1, fontSize: 16 },
+ done: { textDecorationLine: "line-through", color: "#777" },
+ delete: { fontSize: 20, marginLeft: 10 },
+ empty: { textAlign: "center", marginTop: 30, fontSize: 16 },
+});
diff --git a/src/screens/SignInScreen.js b/src/screens/SignInScreen.js
new file mode 100644
index 0000000..0ac8abe
--- /dev/null
+++ b/src/screens/SignInScreen.js
@@ -0,0 +1,98 @@
+import React, { useState, useEffect, useContext } from "react";
+import { View, Image, StyleSheet, KeyboardAvoidingView, Platform, Pressable, Keyboard, Alert } from "react-native";
+import Input, { KeyboardTypes } from "../componets/Input";
+import Button from "../componets/Button";
+import { signInAsync } from "../api/auth";
+import { UserContext } from "../context/UserContext";
+
+
+export default function SignInScreen({ navigation }) {
+ const { user, setUser } = useContext(UserContext);
+ const [email, setEmail] = useState("");
+ const [password, setPassword] = useState("");
+ const [disabled, setDisabled] = useState(true);
+ const [loading, setLoading] = useState(false);
+
+ useEffect(() => {
+ setDisabled(!(email && password));
+ }, [email, password]);
+
+ const onSubmit = async () => {
+ if (disabled || loading) return;
+
+ Keyboard.dismiss();
+ setLoading(true);
+
+
+
+ try {
+ const user = await signInAsync(email.trim(), password);
+
+ setUser(user);
+
+
+ Alert.alert("로그인 성공입니다.");
+ navigation.navigate("List");
+ } catch (error) {
+ Alert.alert("로그인 실패", "아이디나 비밀번호를 확인해주세여");
+
+ console.log('로그인 에러:', error)
+ } finally {
+ setLoading(false);
+ }
+};
+
+
+return (
+
+ Keyboard.dismiss()}>
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: "#fff",
+ paddingHorizontal: 20,
+ paddingTop: 200,
+ alignItems: "center",
+ },
+ image: {
+ width: 250,
+ height: 180,
+ marginBottom: 10,
+ },
+});