GitHub 설정하고 코드 버전 관리하기
Git과 GitHub의 기본 개념을 이해하고, 프로젝트를 Repository에 올려 버전 관리하며 협업 기반을 구축합니다.
GitHub 설정부터 Firebase App Hosting 배포, AI 연동까지
컴퓨터와 대화하는 창을 열어보세요
Command + Space
키를 동시에 누르기$
또는 %
표시가 나타납니다!Windows키 + R
동시에 누르기C:\Users\사용자명>
같은 표시가 나타납니다!터미널에서 보이는 것들이 무엇인지 알아보기
꼭 알아야 할 필수 명령어들을 실습해보세요
pwd
(또는 Windows: cd
) 입력해서 현재 위치 확인ls
(또는 Windows: dir
) 입력해서 폴더 목록 보기cd Desktop
입력해서 바탕화면으로 이동pwd
입력해서 위치가 바뀌었는지 확인cd ..
입력해서 원래 위치로 돌아오기알아두면 편리한 터미널 사용법들
cd Des
입력 후 Tab키를 누르면Desktop
으로 자동완성됩니다.cd ~
또는 cd
만 입력하면 어디서든 홈 폴더(사용자 폴더)로 바로 이동합니다.clear
(Mac) 또는 cls
(Windows) 입력으로 깨끗하게 정리하세요.# Firebase Console에서: 1. 프로젝트 선택 2. 좌측 메뉴에서 'Hosting' > 'App Hosting' 선택 3. 'Get Started' 클릭 4. GitHub 계정 연결 허용
# App Hosting 설정: 1. 'Connect to GitHub' 선택 2. Repository 선택 (예: username/my-todo-app) 3. 배포할 브랜치 선택 (보통 main 또는 master) 4. 빌드 설정 구성
# 빌드 설정 예시: Build command: npm run build Output directory: .next Node.js version: 18 # package.json의 scripts 확인: { "scripts": { "build": "next build", "start": "next start" } }
# Firebase App Hosting 환경 변수: NEXT_PUBLIC_FIREBASE_API_KEY=your_api_key NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your_domain NEXT_PUBLIC_FIREBASE_PROJECT_ID=your_project_id # .env.local 파일은 GitHub에 업로드하지 않도록 주의!
# 자동 배포 프로세스: 1. GitHub에 코드 push 2. Firebase App Hosting이 자동으로 감지 3. 빌드 프로세스 실행 4. 성공 시 자동으로 배포 완료 5. 고유한 URL로 웹사이트 접근 가능
# Firebase Console에서: 1. Extensions 메뉴 이동 2. 'Vertex AI in Firebase' 검색 3. 'Install' 클릭 4. 프로젝트 설정 및 결제 계정 연결 (무료 할당량 있음) 5. 설치 완료 후 구성
// functions/index.js const { onCall, HttpsError } = require('firebase-functions/v2/https'); const { VertexAI } = require('@google-cloud/vertexai'); const vertexAI = new VertexAI({ project: 'your-project-id', location: 'us-central1' }); exports.generateAIResponse = onCall(async (request) => { try { const { prompt } = request.data; const generativeModel = vertexAI.getGenerativeModel({ model: 'gemini-1.5-flash' }); const result = await generativeModel.generateContent(prompt); const response = result.response; return { success: true, text: response.candidates[0].content.parts[0].text }; } catch (error) { throw new HttpsError('internal', 'AI 응답 생성 실패'); } });
// components/AIChat.js import { getFunctions, httpsCallable } from 'firebase/functions'; import { useState } from 'react'; const AIChat = () => { const [message, setMessage] = useState(''); const [aiResponse, setAiResponse] = useState(''); const [loading, setLoading] = useState(false); const generateResponse = httpsCallable( getFunctions(), 'generateAIResponse' ); const handleSubmit = async (e) => { e.preventDefault(); setLoading(true); try { const result = await generateResponse({ prompt: message }); setAiResponse(result.data.text); } catch (error) { console.error('AI 응답 실패:', error); } finally { setLoading(false); } }; return ( <div> <form onSubmit={handleSubmit}> <input value={message} onChange={(e) => setMessage(e.target.value)} placeholder="AI에게 메시지를 보내보세요" /> <button type="submit" disabled={loading}> {loading ? '생각중...' : '전송'} </button> </form> {aiResponse && ( <div className="ai-response"> <h4>AI 응답:</h4> <p>{aiResponse}</p> </div> )} </div> ); };
// 감정 일기장 예시 const analyzeEmotion = async (diary) => { const prompt = `다음 일기의 감정을 분석하고 위로의 말을 해주세요: "${diary}" 감정 분석: (긍정적/부정적/중립적) 위로의 말: (따뜻하고 공감적인 메시지)`; const result = await generateResponse({ prompt }); return result.data.text; }; // TODO 응원 기능 예시 const generateEncouragement = async (todoItem) => { const prompt = `다음 할일에 대해 동기부여가 되는 응원 메시지를 작성해주세요: 할일: "${todoItem}" 짧고 에너지 넘치는 응원 메시지를 작성해주세요.`; const result = await generateResponse({ prompt }); return result.data.text; };
# Firebase Console에서: 1. Authentication 메뉴 이동 2. 'Get started' 클릭 3. Sign-in method 탭에서 원하는 로그인 방법 활성화: - Google (OAuth 2.0) - Email/Password - 기타 소셜 로그인 (Facebook, Twitter 등)
# Firebase Console에서 Google 설정: 1. Google 로그인 방법 활성화 2. 프로젝트 지원 이메일 설정 3. OAuth 동의 화면 구성 (선택사항) # 웹 앱에서 사용할 설정 정보 확인: - Web client ID - Web client secret (자동 관리됨)
// lib/firebase.js - Firebase 초기화 import { initializeApp } from 'firebase/app'; import { getAuth, GoogleAuthProvider } from 'firebase/auth'; const firebaseConfig = { // Firebase 설정 }; const app = initializeApp(firebaseConfig); export const auth = getAuth(app); export const googleProvider = new GoogleAuthProvider(); // components/Login.js import { signInWithPopup, signOut } from 'firebase/auth'; import { auth, googleProvider } from '../lib/firebase'; import { useAuthState } from 'react-firebase-hooks/auth'; const Login = () => { const [user, loading, error] = useAuthState(auth); const signInWithGoogle = async () => { try { await signInWithPopup(auth, googleProvider); } catch (error) { console.error('로그인 실패:', error); } }; const logOut = () => { signOut(auth); }; if (loading) return <div>로딩 중...</div>; return ( <div> {user ? ( <div> <p>안녕하세요, {user.displayName}님!</p> <img src={user.photoURL} alt="프로필" /> <button onClick={logOut}>로그아웃</button> </div> ) : ( <button onClick={signInWithGoogle}> Google로 로그인 </button> )} </div> ); };
// 사용자별 Firestore 데이터 구조 // /users/{userId}/todos/{todoId} import { doc, collection, addDoc, query, where, getDocs } from 'firebase/firestore'; import { db } from '../lib/firebase'; // 사용자별 TODO 저장 const addUserTodo = async (userId, todoData) => { const userTodosRef = collection(db, 'users', userId, 'todos'); await addDoc(userTodosRef, { ...todoData, createdAt: new Date(), userId: userId }); }; // 사용자 TODO 목록 가져오기 const getUserTodos = async (userId) => { const userTodosRef = collection(db, 'users', userId, 'todos'); const snapshot = await getDocs(userTodosRef); return snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })); }; // 컴포넌트에서 사용 const TodoList = () => { const [user] = useAuthState(auth); const [todos, setTodos] = useState([]); useEffect(() => { if (user) { getUserTodos(user.uid).then(setTodos); } }, [user]); const handleAddTodo = async (todoText) => { if (user) { await addUserTodo(user.uid, { text: todoText, completed: false }); // TODO 목록 새로고침 const updatedTodos = await getUserTodos(user.uid); setTodos(updatedTodos); } }; if (!user) { return <Login />; } return ( <div> <h2>{user.displayName}님의 TODO 리스트</h2> {/* TODO 목록 렌더링 */} </div> ); };
// firestore.rules rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // 사용자는 자신의 데이터만 읽고 쓸 수 있음 match /users/{userId}/{document=**} { allow read, write: if request.auth != null && request.auth.uid == userId; } // 공개 데이터 (필요시) match /public/{document=**} { allow read: if true; allow write: if request.auth != null; } } }
2주차에 만든 자신의 웹사이트에 외부 API(AI, 공공데이터 등)를 자유롭게 연동하여 새로운 기능을 추가하고, 서비스의 가치를 높여보세요.