3학년 2학기 지능웹설계 과목의 텀프로젝트 결과물을 소개하겠다.

지능웹설계에서는 jsp를 이용한 웹 페이지 구성, 서버 연결, 데이터베이스 연결을 다뤘다.

학기 중에 배운 내용들을 모두 활용해야하는 개인 프로젝트의 주제는 자유였으며,

나는 내가 가장 좋아하는 게임인 스타듀밸리의 팬 페이지를 주제로 프로젝트를 진행했다.

 

프로젝트는 Eclipse에서 Dynamic Web Project를 생성하여 개발을 진행하였고

JSP를 기반으로 만들었으며 css는 부트스트랩을 활용했고 데이터베이스는 MySQL과 연결했다.

실제 서버에 등록하진 않았고 Tomcat을 이용해서 로컬 호스트 상에서 실행시킬 수 있는 상태까지 개발했다.

메인 화면

웹 페이지의 기본 틀은 상단에 메뉴바가 있고 중앙에 웹 페이지의 내용이 있다.

메뉴바를 보면 메인 화면 / 캐릭터 소개 / 커뮤니티 / 마이페이지 / 사이트 평가 / 로그인 및 회원가입 기능이 있다.

 

다국어 처리

화면 왼쪽, 오른쪽에 있는 주니모 (사과 캐릭터) 들이 있는데

왼쪽 주니모는 한국어로, 오른쪽 주니모는 영어로 사이트 번역을 해준다.

 

회원가입

메뉴바 오른쪽에 있는 회원가입 버튼을 클릭하면 회원가입 폼으로 이동하게 된다.

아이디, 비밀번호에 대해서는 유효성 검사를 거치게 된다.

회원가입 직후에는 로그인 폼을 거치지 않고 바로 로그인을 할 수 있다. (쿠키 이용)

 

캐릭터 소개

스타듀밸리 팬 페이지인만큼, 게임에 대한 정보를 사이트에서 제공하면 좋겠다고 생각했고

간단하게 캐릭터 소개 페이지만 만들었다.

 

캐릭터 정보 수정

캐릭터 정보를 수정하기 위해서는 관리자 로그인이 필요하다.

이것은 팬 페이지 사용자 로그인과는 별개로 이루어진다.

캐릭터 정보 수정 완료 화면이다.

 

커뮤니티 공간

팬 페이지에서는 유저들간의 소통이 원활하게 이루어져야한다고 생각했다.

그래서 각 유저들이 자신의 플레이 내용을 공유할 수 있도록

게시물을 작성하고 확인하는 기능을 제공한다.

저 스크린샷은 내가 직접 찍은 플레이 장면인데 가을에 심은 호박 중 거대 호박이 2개나 자랐다.

게시물에는 제목, 내용, 작성자, 작성일, 사진이 나와있다.

그리고 해당 게시물에 다른 사람들도 댓글을 등록하여 소통할 수 있다.

 

댓글 등록 및 삭제

본인이 등록한 댓글 옆에는 빨간색 X버튼이 있는데

이 버튼을 클릭하면 댓글을 삭제할 수 있다.

댓글 작성은 로그인한 사용자만 가능하다.

 

게시물 작성

게시물 작성 역시 로그인한 사용자만 이용 가능하고

제목, 내용, 이미지 파일을 첨부하면 된다.

게시물이 등록된 모습이다.

 

마이페이지

사용자 로그인을 한 상태라면 마이페이지에서 자신이 작성한 게시물과 댓글을 확인할 수 있다.

게시물 제목과 댓글 내용을 클릭하면 관련 게시물로 바로 이동한다.

 

사이트 평가

사이트 평가는 게시물의 댓글 등록하는 것과 거의 유사하다.

실제로 운영되는 사이트는 아니지만, 팬 페이지를 만든다면

운영자와 이용자들간의 원활한 소통과 피드백이 이루어져야 한다고 생각해서 만든 메뉴이다.


프로젝트를 자체 평가하자면 큰 스케일로, 디테일을 많이 살리지 못해서 조금 아쉬운 느낌이 있다.

그래도 학기 내내 배운 JSP 내용들을 총 집합하여 웹 페이지를 구성했다는 점,

MySQL 데이터베이스를 이클립스에 연결하여 DB를 이용한 첫 개발이라 의미가 있는 웹 개발 프로젝트였다.

 

https://github.com/askges20/StardewValleyFanPage

 

askges20/StardewValleyFanPage

2020-2 지능웹설계 프로젝트. Contribute to askges20/StardewValleyFanPage development by creating an account on GitHub.

github.com

⬆ 해당 프로젝트는 GitHub에 소스 코드를 업로드하였다.

3학년 2학기 컴퓨터그래픽스 과목에서는 지금까지 배운 그래픽스 이론들을 활용하는

자유 주제의 텀프로젝트가 주어졌다.

개발 형태, 주제, 플랫폼 등 아무런 제한 없이 정말 자유롭게 진행하면 되는 프로젝트였고

나는 유니티3D를 이용한 게임을 개발해보았다.

프로젝트를 시작할 때 나는 유니티를 다뤄본 적이 없었고, 심지어 C#을 공부한 적도 없었다.

지금까지 C언어, 자바, 파이썬 등의 프로그래밍 언어를 배웠기 때문에 프로그래밍에 대한 지식은 있으니까

인터넷에 나온 강좌들을 찾아보면서 공부하는 동시에 개발을 해보기로 했다.

프로젝트 이름은 "치킨런", 닭이 장애물을 피해 병아리를 모아 목표지점에 도달하는 게임이다.

프로젝트 개요 및 목표

개요

장애물을 피해서 목표 지점까지 도달하는 3D 러닝 게임을 제작함

목표

- Unity3D 환경에서 게임을 제작함

- 다양한 컴퓨터그래픽스 이론을 적용하여 프로젝트를 진행함

- 닭이 모든 병아리를 모아서 목표 지점에 도착하는 러닝 게임을 제작함

프로젝트 전체 시스템 구성도

유니티에서 오브젝트에 C# 스크립트를 연결시켜 게임을 개발했다.

먼저 오브젝트는 주요 오브젝트, 장애물 및 지형, 사용자 인터페이스, 그 외의 오브젝트로 나눌 수 있다.

주요 오브젝트는 플레이어의 캐릭터인 닭, 플레이어가 모아야하는 아이템 병아리,

플레이어 시점의 카메라, 게임의 전반적인 관리를 담당하는 게임 매니저가 있다.

맵에 있는 장애물을 간략하게 표현해보았다.

스크립트는 주요 오브젝트, 장애물 및 지형, 그 외에 관련된 스크립트가 있다.

프로젝트 내 주요 기능 설명

카메라가 캐릭터를 잡아주되, 캐릭터와 일정 거리를 유지하면서 이동할 수 있도록 오프셋을 설정한다.

플레이어는 3인칭 시점에서 게임을 플레이한다.

닭의 진로를 방해하는 장애물들은 반복적으로 좌우 또는 상하로 이동한다.

장애물과 닿았을 때, 맵 밖으로 떨어졌을 때 다시 시작 지점에 리스폰된다.

동적인 효과를 주기 위해 애니메이터,애니메이터 컨트롤러를 사용했다.

플레이어의 캐릭터인 닭은 플레이어의 조작에 따라 다른 액션을 취하고

병아리들은 제자리에서 3개의 행동을 반복한다.

프로젝트 설계 방법

이 게임은 PC에서 실행하는 게임이기 때문에 키보드의 방향키를 이용하여 이동하고, 스페이스바로 점프를 한다.

게임 시작과 동시에 타이머가 시작하고 필드에 있는 병아리를 모두 모은 후 목표 지점에 도달하면 게임이 끝난다.

프로젝트 수행 결과

 

 


프로젝트 후기

유니티를 처음 사용한 것 치고는 그래도 나름 게임 같은 결과물이 나왔다.

사실 맵을 완주하는 것은 한 번도 떨어지지 않고 직진하면 1분이 걸려서 굉장히 짧고 간단한 게임이라고 할 수 있다.

그런데 게임 제작을 완료하고 주변 사람들에게 한 번 플레이해보라고 게임 파일을 보내줬는데

10, 14트만에 성공한 친구들도 있었고 대체로 게임이 어렵다는 평을 들었다. 10분 이상 플레이했다고ㅎㅎ

현재 상태에서 개선할만한 점을 몇 가지 생각해보았다.

- 단순히 제자리에서 움직이는 장애물뿐만 아니라 플레이어 캐릭터를 따라오는 인공지능적인? 방해자를 만든다.

- 커브 구간을 추가하여 맵을 다채롭게 만든다. (카메라도 같이 회전)

- 이동 방향에 따라 닭이 바라보는 방향도 자연스럽게 만든다.

- PC뿐만 아니라 모바일 플랫폼에서도 플레이 가능하도록 앱 형식으로 만든다.

 

 

https://github.com/askges20/ChickenRun

 

askges20/ChickenRun

2020-2 컴퓨터그래픽스 프로젝트. Contribute to askges20/ChickenRun development by creating an account on GitHub.

github.com

⬆ 해당 프로젝트는 현재 가상 조이스틱을 이용하여 플레이할 수 있는 앱으로 수정하였으며 GitHub에 업로드되어있다.

'App > Unity3D' 카테고리의 다른 글

컴퓨터그래픽스 프로젝트 3D 러닝 게임 "치킨런"  (0) 2021.06.15

리액트 네이티브 & Expo

리액트 네이티브

리액트(React) + 네이티브(Native)

리액트는 JS 기반인데 개발하다보면 카카오톡 로그인 등 안드로이드, iOS 각각의 코드를 알아야하는 상황이 생김 → Expo를 이용함

 

Expo

  • 리액트 네이티브 코어 앱 개발 코어 기술을 Expo로 감싸서 JS로만 개발할 수 있는 환경을 구축하도록 도와주는 역할
  • Expo 클라이언트 앱-Expo 서버를 킨다 → QR 코드를 찍어서 개발중인 앱을 확인한다.

개발 환경 준비

  1. Node & NPM-Node.js로 JS 개발 환경 구축-Node.js 설치 시 NPM 자동 설치
  2. -유용한 JS 도구를 가지고 올 때 NPM(Node Package Manager) 사용
  1. Yarn-NPM보다 더 효율적으로 JS 도구를 가져올 수 있는 도구
    💡
    npm install -g yarn * -g : 컴퓨터에 전역적으로 설치한다는 옵션
  2. -NPM을 이용해서 설치
  1. Expo 명령어 도구 설치-Expo 도구 : NPM을 이용해서 설치
  2. 💡
    npm install -g expo-cli
  1. Expo 가입 및 로컬에 Expo 계정 세팅
    • cmd창에서 Expo 서비스 로그인
    💡
    expo login —username 사용자이름
  1. Expo 실행하기
    • 바탕화면에 sparta study 생성
    • VS code에서 Open Folder - sparta study 폴더 선택
    • View - Terminal 클릭해서 터미널 창 열기
    • expo init으로 프로젝트 생성
    💡
    expo init sparta-honeytip-yewon
    *이때 오류나는 경우 터미널을 Powershell이 아닌 Command Prompt로 변경
    • 개발하기 위해 폴더 이동
    💡
    cd sparta-honeytip-yewon
    • expo 시작
    💡
    expo start
    *Expo 클라이언트 앱으로 개발을 진행할 것(같은 와이파이 상에서 연결이 안되는 문제 : LAN → Tunnel로 변경 후 새 QR 코드 인식해서 해결)
  2. → 구글 플레이스토어에서 앱 다운 후 QR 인식 (동일한 WIFI 연결)
  1. Expo 파일 간단 설명
    • assets 폴더 : 이미지 폴더
    • node_modules : 도구 폴더
    • App.js : 화면이 되는 파일
    • app.json : 앱 배포 시 설명서

React Native 태그, Styles, Flex

App.js

import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

//메인화면
export default function App() {
	//화면 반환
  return (
    <View style={styles.container}>
      <Text>Open up App.js to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

//화면을 꾸밈
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});
  • <View>, <Text> 등 꺽쇠를 이용한 부분 → JSX라고 함 (화면을 그리는 문법)
  • <View> </View> 처럼 태그로 화면의 한 영역을 구성할 때 → 엘리먼트라고 함

 

  • 사용할 태그는 import를 이용해서 가져온다.
import { StyleSheet, Text, View } from 'react-native';
  • 모든 엘리먼트는 감싸는 최상위 엘리먼트가 있어야 한다.
  • return을 이용해 렌더링할 때 항상 소괄호로 감싸져있어야 한다.
export default function App() {
  return (
    <View style={styles.container}>
      <Text>Open up App.js to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  );
}

 

View 태그

  • <View> : 화면의 영역을 잡아주는 엘리먼트

 

Text 태그

  • <Text> : 앱에 글을 작성하기 위해 사용하는 엘리먼트
  • 문자는 반드시 Text 태그 안에 써야함!

 

ScrollView 태그

import React from 'react';
import { StyleSheet, Text, View, ScrollView } from 'react-native';

export default function App() {
  return (
    <ScrollView style={styles.container}>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </View>
    </ScrollView>
  );
}
  • <ScrollView> : 감싼 엘리먼트 스크롤이 가능해진다.

 

Button 태그

import React from 'react';
import { StyleSheet, Text, View, Button, Alert } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>아래 버튼을 눌러주세요</Text>
        <Button 
          style={styles.buttonStyle} 
          title="버튼입니다 "
          color="#f194ff" 
          onPress={function(){
            Alert.alert('팝업 알람입니다!!')
          }}
        />
        <Button 
            style={styles.buttonStyle} 
            title="버튼입니다 "
            color="#FF0000" 
            onPress={()=>{
              Alert.alert('팝업 알람입니다!!')
            }}
          />
          </View>
    </View>
  );
}
  • <Button> : 버튼을 만들 수 있는 엘리먼트
  • title 속성 : 버튼 안에 넣을 문자
  • color 속성 : 버튼 색상
  • onPress 속성 : 버튼 클릭 시 실행할 함수 연결

 

TouchableOpacity

  • <TouchableOpacity> : 버튼과 비슷한 역할을 함, 대신 화면에 영향을 주지 않음
  • 임의의 영역과 디자인에 버튼 기능을 추가할 때 주로 사용할 태그

 

Image 태그

import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
//이렇게 상단에 가져와 사용할 이미지를 불러옵니다
import favicon from "./assets/favicon.png"

export default function App() {
  return (
    <View style={styles.container}>
      <Image 
        source={favicon}
				// 사용설명서에 나와 있는 resizeMode 속성 값을 그대로 넣어 적용합니다
        resizeMode={"repeat"}
        style={styles.imageStyle}
      />
    </View>
  );
}
  • <Image> : 이미지를 넣는 태그
  • import를 통해 assets 폴더의 이미지 파일을 가져온 다음 사용
  • source : import한 이미지
  • resizeMode : 이미지를 보여주는 방식-repeat : 이미지가 반복-그 외 contain, stretch, center
  •  
  • -cover : 이미지가 화면 전체에 꽉 차게 보여줌
import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
//이렇게 상단에 가져와 사용할 이미지를 불러옵니다
import favicon from "./assets/favicon.png"

export default function App() {
  return (
    <View style={styles.container}>
			{/*이미지 태그 soruce 부분에 가져온 미지 이름을 넣습니다 */}
      <Image 
        source={{uri:'https://images.unsplash.com/photo-1424819827928-55f0c8497861?fit=crop&w=600&h=600%27'}}
				// 사용설명서에 나와 있는 resizeMode 속성 값을 그대로 넣어 적용합니다
        resizeMode={"cover"}
        style={styles.imageStyle}
      />
    </View>
  );
}
  • 외부 이미지를 가져와서 사용하는 방법
  • source에 uri 지정

*코드가 너무 길면 alt+z를 눌러서 한 화면에 코드가 다 들어오도록 설정

 

Styles

import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>스파르타 코딩클럽!!</Text>
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    justifyContent:"center",
    alignContent:"center"
  },
  textContainer: {
    margin:10,
    padding: 10,
    borderRadius:10,
    borderWidth:2,
    borderColor:"#000",
    borderStyle:"dotted",

  },
  textStyle: {
    color:"red",
    fontSize:20,
    fontWeight:"700",
    textAlign:"center"
  }
});
  • const style : 값의 재할당이 불가능한 style 변수 생성
  • StyleSheet에 딕셔너리를 넘겨줌
  • margin, padding, borderRadius, borderWidth, borderColor, borderStyle
  • color, fontSize, fontWeight, textAlign

 

Flex

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <View style={styles.containerOne}>

      </View>
      <View style={styles.containerTwo}>
        <View style={styles.innerOne}>
         
        </View>
        <View style={styles.innerTwo}>
          <Text>!!컨텐츠!!</Text>
        </View>

      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex:1
  },
  containerOne: {
    flex:1,
    backgroundColor:"red"
  },
  containerTwo:{
    flex:2,
    flexDirection:"row",
    backgroundColor:"yellow"
  },
  innerOne: {
    flex:1,
    backgroundColor:"blue"
  },
  innerTwo: {
    flex:4,
    flexDirection:"row",
    justifyContent:"flex-end",
    backgroundColor:"orange"
  }
});
  • flex : 레이아웃 비율 (상대적)
  • flexDirection : flex 방향 지정
  • 상하 : column (기본) / 좌우 : row
  • justifyContent : flexDirection에 따라 정렬
  • flex-start, flex-end, center를 가장 자주 씀, 그 외 space-around, space-between, space-evenly
  • alignItems : flexDirection 방향과 반대로 정렬 (flex 영역 내에서 사용 가능)
  • alignSelf : flex 없어도 가능
  • numberOfLines={3} : 텍스트 잘리는 부분 ... 으로 대체

 

앱&자바스크립트 모듈, 반복문

  • App.js : 모듈 시스템에 의해서 내보내짐
  • 앞으로 여러 파일들을 만들 때 export default function을 이용해서 내보낼 것
export default function App() {...}

 

  • data.json 파일 : 딕셔너리 + 리스트 구조
  • App.js에 data.json 파일 import
import data from './data.json'

 

  • data.tip으로 json 파일의 tip 가져오기
let tip = data.tip;
let todayWeather = 10 + 17;
let todayCondition = "흐림"

 

  • App.js JSX 문법 안에서 map을 이용한 반복문
  • 반복문을 돌릴 때 가장 최상위 태그에는 key값이 주어져야 한다. (key는 유니크함)
<View style={styles.cardContainer}>
         {/* 하나의 카드 영역을 나타내는 View */}
         { 
          tip.map((content,i)=>{
            return (<View style={styles.card} key={i}>
              <Image style={styles.cardImage} source={{uri:content.image}}/>
              <View style={styles.cardText}>
                <Text style={styles.cardTitle} numberOfLines={1}>{content.title}</Text>
                <Text style={styles.cardDesc} numberOfLines={3}>{content.desc}</Text>
                <Text style={styles.cardDate}>{content.date}</Text>
              </View>
            </View>)
          })
         }
      </View>

 

  • JSX 안에서 중괄호 { }를 쓰면 그 안에서 자바스크립트 문법을 쓸 수 있다!
<Text style={styles.weather}>오늘의 날씨: {todayWeather + '°C ' + todayCondition} </Text>

 

삼항연산자

let result = 조건 ? 참일때 : 거짓일때
let result = 10>2 : '참' : '거짓'

tip.map((content,i)={
	return i%2==0 ? (<View>...</View>) : (<View>...</View>)
})

 

숙제

어바웃 페이지 만들기

Uploaded by Notion2Tistory v1.1.0


지난 주 1주차 수업에서는 자바스크립트의 기초를 배웠고

이번 주에는 본격적으로 리액트를 이용하여 앱을 만들어보는 시간을 가졌다.

Node.js, NPM, Expo 등 미리 세팅해야할 사항이 많아보여서 처음에는 약간 겁을 먹었으나

세팅을 무사히 마친 후 VS Code에서 JSX의 다양한 태그들을 활용하며 레이아웃을 구성하니 흥미로웠다.

 

태그를 사용하여 레이아웃을 구성하는 것은 안드로이드 스튜디오와 비슷해서 낯설지 않았고

이미 css를 공부했었기 때문에 StyleSheet를 활용하여 꾸미는 것도 익숙했다.

아직 flex 개념이 헷갈리는데 추가적으로 공부를 해서 익혀야겠다. (안드로이드 스튜디오 layout_gravity가 생각나는 속성이었다.)

 

Expo 클라이언트 앱을 이용하여 실시간으로 내가 수정한 코드가 반영된 모습을 볼 수 있는 점이 정말 편리했다.

안드로이드 스튜디오 같은 경우에는 미리보기 창으로 레이아웃을 얼추 볼 수 있긴 하나

제대로 실행시키려면 빌드를 해야하기 때문에 시간이 걸려서 은근 번거로운데

Expo는 ctrl+s 할 때마다 바로 핸드폰 화면에 수정 사항이 반영되기 때문에 앞으로 개발하면서 시간 단축이 많이 될 것 같다는 생각이 들었다.

또한 오류 메세지도 자세하게 나오는 편이라 어느 부분에서 오류가 났는지 확인하기 쉬웠다.

 

이번 주 강의를 열심히 수강한 결과, 마지막에 첨부한 이미지처럼 숙제로 어바웃 페이지를 구현할 수 있었다.

오늘 막 리액트에 입문한 것 치고 많은 것을 배우고 그것을 응용할 수 있는 능력을 가지게 된 것 같아 좋았다!

5월 초 : 아키텍처 결정 및 개발 환경 세팅

우리 프로젝트는 안드로이드 스튜디오로 진행하는 것으로 생각했었는데

이왕 프로젝트를 진행하는 안드로이드, iOS 모두 지원 가능한 앱을 만들까? 라는 얘기가 잠깐 나왔었다.

네이티브 앱? 리액트? 웹 앱? 등 여러 키워드가 회의 시간에 제시되었지만

결론적으로는 원래 계획대로 안드로이드 스튜디오에서만 구현하기로 했다.

우리 팀은 서버 숙련자가 없기도 하고

앱 자체 기능을 구현하는데도 꽤 오랜 시간이 걸릴 것 같아서

서버단의 작업은 최소화하는게 좋을 것이라고 판단했다.

 

서버 구축에 대해 구글링을 많이 해봤는데

firebase를 이용해서 서버리스 아키텍처를 적용한 안드로이드 스튜디오 프로젝트 사례가 많이 있었고

firebase 이용 관련 문서가 잘 나와있는 것 같아 인터넷을 참고해서 충분히 구현할 수 있을 것이란 생각이 들어서

google에서 지원하는 firebase를 이용하는 것으로 결정했다.

또한 우리가 기획한 기능들 중 챗봇을 이용한 상담 기능이 있어서

챗봇 같은 경우 google의 dialogflow를 이용하기로 했다.

결론적으로 우리 팀의 아키텍처는

1. 안드로이드 스튜디오내에서 UI, 로직을 처리하고

2. dialogflow API를 가져와서 챗봇을 구현하고

3. firebase 서버와 연동하여 서버 운영, 실시간 데이터베이스를 사용하는 것이다.

 

 

코드 형상 관리는 GitHub를 이용해서 진행하는데 안드로이드 스튜디오와 GitHub 연동은 생각보다 수월했다.

 

Firebase 연동도 무난하게 하는 듯 했으나...

실시간 데이터베이스를 이용하기 위해 앱 수준의 gradle 파일에 google service 4.3.6버전 dependency를 추가했는데

빌드를 시도할 때마다 자꾸 오류가 나는 것이었다.

구글링해도 해당 오류에 대한 자료가 너무 없길래 몇 시간동안 절망했는데

알고보니 4.3.6버전 자체 버그가 있던 것이다,,, 아래는 해당 이슈

https://github.com/google/play-services-plugins/issues/176

Could not find setVariantDir after 4.3.6 · Issue #176 · google/play-services-plugins

Describe the bug A problem occurred configuring project ':mobile'. > Failed to notify project evaluation listener. > com.android.build.gradle.internal.crash.ExternalApiUsageException:...

github.com

4.3.6 버전에서 삭제된 메소드를 여전히 호출하는 메소드가 있었던 것..

해당 이슈가 발생한지 얼마 안된 시점이었는데

다행히도(?) 며칠 만에 버그 픽스가 된 4.3.8 버전이 나왔고 Firebase DB와 연동을 마쳤다.

 

5월 중순 : 개발 시작 (레이아웃 구성)

Figma 툴을 이용해서 작성한 앱 화면 프로토타입을 바탕으로

팀원들이 각자 맡은 역할대로 안드로이드 스튜디오 안에서 레이아웃을 구현했다.

현재는 디자인 고려 안하고 화면 해상도에 맞게 레이아웃, 버튼 배치만 한 상태이다. (위의 이미지는 메인 화면)

디자인보단 기능 구현이 우선이라고 생각해서 색 조합이나 이미지뷰는 나중에 고려할 듯 하다.

나는 앱의 주요 기능들 중 일기장 부분 레이아웃을 맡아 일기 내용/작성/수정 페이지 레이아웃을 구현했다.

5월 말 : 일기장 기능 구현 중

우리 팀이 구현할 기능들 중 가장 먼저 일기장 기능을 다뤄보기로 했다.

Firebase DB 사용법을 찾아보며 간단히 일기를 등록하고, 삭제하는 것까지 구현했다.

 

그런데 문제점이 있었으니..

1. MaterialCalendarView

커스텀 캘린더뷰를 구현하기 위해 MaterialCalendar을 활용하려고 하는데

생각보다 MaterialCalendarView와 관련된 자료들이 많이 없으며

특정 부분에서 NullPointerException 에러가 발생하는데 해당 오류의 원인을 찾지 못했다.

2. ViewModel

우리는 MVVM(Model-View-ViewModel) 패턴을 이용하여 개발을 진행하고자 한다.

그런데 안드로이드 스튜디오의 ViewModel과 관련된 자료들을 찾아보았을 때

Kotlin 언어를 이용한 자료들이 대부분.. Java를 사용하여 설명을 작성한 경우가 거의 없었다ㅠㅠ

또한 공식 문서를 읽어보아도 이것을 어떻게 활용해야할지 감이 안와서 난감한 상태다.

 

5월 말에 한번 멘토님과 온라인 미팅을 진행했었다.

본격적인 개발을 하기 앞서 개발 환경 세팅, 아키텍처 결정 등에 많은 시간을 들여서

우리 팀의 개발 속도가 너무 더딘건 아닐지 걱정스러운 마음이 있었는데

멘토님께서는 잘 진행하고 있는 것 같다며 힘이 되는 말씀을 해주셨다.

한이음 프로젝트와 관련된 다양한 조언들을 해주셔서

끝까지 책임감을 가지고 프로젝트를 진행해보겠다는 의지를 다시 한번 다잡을 수 있었다.

4월 5일이 한이음 신청 마감일이었고 우리 팀은 4월 4일에 계획서를 제출했다.

그리고 4월 13일에 프로젝트 개설 심의 결과가 나왔는데

다행히도 개설 승인이 되었다! 한이음 사이트에 팀 블로그가 만들어졌다.

팀 블로그를 보니 팀 총 130만원의 지원비가 있는 것으로 확인된다.

우리 팀은 앱 개발이라 지출이 많을 것 같진 않다.

만약 서버 사용량이 많아진다면 지원비로 요금 지불할지도?

 

한이음 프로젝트 진행은 확정되었으니

본격적인 개발 시작을 앞두고 어떤 아키텍처를 적용할지,

어떤 프레임워크와 API들을 사용할지 고민하기 시작했다.

 

컴공을 4년째 재학 중이지만... 전공 과목으로 다뤄본 프로그램은 생각보다 그렇게 많지 않기도 하고

더군다나 앱 개발은 학교에서 배운 적도 없기 때문에 어떤 기술을 이용해야할지 많이 막막했다.

4월 말에는 한창 중간고사 기간이라 회의를 못하고

시험이 끝난 5월 초에 다시 제대로 프로젝트를 진행하는걸로 결정했다.

한이음 프로젝트를 시작한지 몇달 되긴 했으나

티스토리를 개설한 기념으로(?) 매달 프로젝트 진행 상황을 정리하는 포스팅을 업로드하려고 한다.

 

 


 

우리 학교 교내 비교과 프로그램 중 "문제해결 프로젝트"가 있는데

다양한 문제에 대해서 팀을 구성해서 프로젝트를 진행하는 활동이다.

나는 컴공 4학년이지만 지금까지 이렇다 할 포트폴리오와 프로젝트 경험이 없어서

이번 학기를 빡세게 보내고자, 캡스톤 외의 프로젝트를 찾아보았었다.

그리고 학기 초에 에타에서 앱 개발 프로젝트를 진행할 사람을 모집한다는 글을 보고

쪽지를 보내서 프젝에 참여하게 되었다.

 

앱 개발을 목표로 하여 팀원 구성은 완료되었지만

어떤 앱을 개발할지 주제가 정해지진 않았었다.

따라서 3월에는 앱 개발 방향성에 대한 논의를 진행했고

그 결과 "학교 폭력"과 관련된 앱을 개발하기로 결정했다.

앱의 주요 기능 구성에 대한 회의가 꽤 오래 걸린 듯 하다.

개인적으로는 개발보다 기획이 더 어려운 것 같다..

그리고 교내 비교과 프로젝트에 참여할 뿐 아니라

한이음 ICT 멘토링도 신청하기로 했다.

아무래도 프로젝트 경험이 적은 학생들끼리 모여서 하다보니 어려움이 많을 것 같기에

프로젝트 지도를 해줄 수 있는 멘토의 역할이 필요할 것 같았다.

그래서 3월 중순부터 말까지는 한이음 프로젝트 계획서를 작성했다.

프로젝트 신청을 한다고 해서 다 진행될 수 있는게 아니라

멘티가 올린 계획서를 보고 자신이 이 팀의 멘토가 되겠다! 라고 해주시는 멘토님이 나타나야 한다.

그리고 멘토-멘티의 매칭 이후에 계획서를 보완해서 신청 완료해야

최종적으로 프로젝트 진행 승인 여부가 나온다.

비교과 프로젝트 계획서 작성 내용을 바탕으로 한이음 계획서를 작성해서 한이음 사이트에 올렸고

정말 운 좋게도! 계획서를 올린지 몇 시간 후에 우리 팀을 지도해주시겠다는 멘토님이 나타나셨다.

멘토님의 조언을 바탕으로 계획서 수정을 하는데 정말 계획서 적기가 너무 어려웠다.

글 작성도 그렇고 흐름도같은 시각적 자료를 나타내는게 만만치 않은 일이었다.

 

앱개발이란?

앱 서비스를 만드는 것 → 클라이언트, 서버를 모두 만들어야함

  • 클라이언트 : 사용자가 보는 화면
  • 서버 : 데이터가 있는 곳, 데이터 요청 시 응답해주는 곳

 

앱 개발 : 안드로이드, iOS(아이폰)

  • 안드로이드 → Java & Kotlin
  • iOS → Swift

운영체제가 다르기 때문에 개발 기술 언어가 다르며, 둘 다 러닝 커브 (허들) 존재

 

앱개발 종류

  1. 네이티브 앱 : 안드로이드, iOS를 각각 개발
  1. 하이브리드 앱 : 웹 사이트를 만들고 간단히 배포하는 앱
  1. 크로스 플랫폼 앱 : JS 하나의 언어로 두 개의 플랫폼의 앱을 제작 (강의에서 다룰 것)

 

리액트 네이티브 (React Native)

  • 크로스 플랫폼 앱 개발 언어 중 하나
  • 페이스북에서 만들었고 지원함
  • 리액트(React.js) 라이브럴/프레임워크를 기반으로 앱 제작하는 기술
  • 자바스크립트(JS)로 개발 가능

 


 

Javascript 기초

js는 웹 개발에서만 사용되는 기술이 아닌가? → 아니다. (리액트 네이티브가 js 기반)

js를 학습하면 웹/앱 개발 가능

 

크롬 F12 콘솔창에서 실습 진행

console.log("hello world")

console.log → 화면에 값을 출력하는 함수

 

  • F12 콘솔창 점 세개 버튼 클릭 → Dock side에서 팝업으로 띄울 수 있음
  • 상단의 clear console 버튼을 클릭해서 콘솔창 정리 가능 (변수는 그대로 유지)
  • Shift+Enter로 여러 줄 입력 가능

 

변수

변수 선언

  • let 이용
let num = 20
console.log(num) //20

 

숫자형 및 문자형 변수

let a = 1
let b = 2
let c = a + b
console.log(c) //3

let first = 'yewon'
let last = 'jeong' //큰따옴표 or 작은따옴표로 문자열
console.log(first+" "+last) //yewon jeong

 

변수 이름 규칙

let firstName //카멜 케이스 (camel case)
let first_name // 스네이크 케이스 (snake case)

 

const 변수

  • 값을 재할당할 수 없는 변수
let num = 100
const num2 = 1000
num = 200
num2 = 2000
console.log(num)
console.log(num2)

→ 위의 코드 실행 시 오류 발생

 

💡
Uncaught TypeError: Assignment to constant variable. at <anonymous>:4:6

const로 선언한 변수는 값을 바꿀 수 없기 때문

 

리스트

리스트란?

  • 여러 데이터들을 담을 수 있는 자료형
  • 인덱스는 0부터 시작
let a_list = [1,2,3,4,'yewon',6,'jeong']

//두 번째 값을 꺼낸다 (인덱스 1)
console.log(a_list[1]) //2

 

값 추가하기

  • push 함수 이용
a_list.push('sparta')
console.log(a_list) //[1, 2, 3, 4, "yewon", 6, "jeong", "sparta"]

 

길이

  • length
a_list.length //8

 

딕셔너리

딕셔너리란?

  • 사전 형식
  • key : value
let a_dict = {"name":"yewon", "age":23}
console.log(a_dict["name"])
a_dict["height"] = 200 //값 추가
console.log(a_dict) //{name: "yewon", age: 23, height: 200}

 

리스트, 딕셔너리 복합 구조

let names = [{"name":"yewon", "age":23}, {"name":"yewon2","age":23}]
console.log(names)

실행 결과

💡
(2) [{…}, {…}] 0: {name: "yewon", age: 23} 1: {name: "yewon2", age: 23} length: 2 __proto__: Array(0)

 

names.push({"name":"yewon3","age":23}) //3
console.log(names)
names[1]["age"] //23

 

JSON 데이터 구조

*크롬 확장 프로그램 JSON view 설치

 

함수

기본 제공 함수

  • 나머지 구하기 : %
  • 대문자로 바꾸기 : toUpperCase()
  • 특정 문자로 문자열을 나누기 : split() (ex. split('.') , split('@') ...)
  • 문자열 합치기 : join()
let myname = "jeongyewon"
console.log(myname.toUpperCase()) //JEONGYEWON

let email = "yewon@gmail.com"
console.log(email.split('@')) //["yewon", "gmail.com"] 리스트 형식
console.log(email.split('@')[1]) //gmail.com
console.log(email.split('@')[1].split('.')) //["gmail", "com"]
console.log(email.split('@')[1].split('.')[1]) //com

let txt = "서울시-마포구-망원동"
let names = txt.split("-")
console.log(names) //["서울시", "마포구", "망원동"]
console.log(names.join('>')) //서울시>마포구>망원동

 

함수 만들기

  • 함수 이름 지정
  • 파라미터 이용
  • return을 이용하여 리턴값 반환
function funcName(){
    console.log("함수")
}
funcName() //함수

function sum(num1,num2){
    console.log(num1+num2)
}
sum(10,20) //30

function minus(num1,num2){
    return num1-num2
}
let result = minus(100,10) //변수에 리턴값 저장
console.log(result) //90

 

  • 리터럴 함수 선언 방식 : 변수에 함수를 저장
let a = function(){
    console.log("리터럴 함수 방식")
}
a()

 

조건문

if - else if - else

function is_adult(age){
    if(age>20){
        console.log("성인")
    }else if(age>10){
        console.log("청소년")
    }else{
        console.log("어린이")
    }
}
is_adult(30) //성인

 

AND 연산자

  • 모든 조건이 참이여야 참
function is_adult(age, sex){
	if(age > 20 && sex == '여'){
		alert('성인 여성')
	} else if (age > 20 && sex == '남') {
		alert('성인 남성')
	} else {
		alert('청소년이에요')
	}
}

 

OR 연산자

  • 하나라도 참이면 참
function is_adult(age, sex){
	if (age > 65 || age < 10) {
		alert('탑승하실 수 없습니다')
	} else if(age > 20 && sex == '여'){
		alert('성인 여성')
	} else if (age > 20 && sex == '남') {
		alert('성인 남성')
	} else {
		alert('청소년이에요')
	}
}
is_adult(25,'남') //성인 남성

 

반복문

for문

  • 시작 조건, 반복 조건, 더하기
for(let i=0;i<10;i++){
    console.log(i)
}
// 0~9까지 출력

 

  • 리스트와 같이 이용
let people=['철수','영희','민수','형준','기남','동희']
for(let i=0;i<people.length;i++){
    console.log(people[i])
}

 

  • 리스트, 딕셔너리 복합 구조
let scores = [
	{'name':'철수', 'score':90},
	{'name':'영희', 'score':85},
	{'name':'민수', 'score':70},
  {'name':'형준', 'score':50},
  {'name':'기남', 'score':68},
  {'name':'동희', 'score':30},
]

for (let i=0;i<scores.length;i++){
    if(scores[i]['score']<70){
        console.log(scores[i]); //70점 미만의 점수인 경우에만 출력
    }
}

 


 

앱개발에 자주 쓰이는 Javascript

화살표 함수

  • 함수를 짧게 선언할 수 있음
  • function 대신 () ⇒ 이용
let a = () => {
		console.log("arrow function")
}
a();

 

비구조 할당 방식

  • key에 따옴표를 붙이지 않아도 됨
  • . 을 이용해서 딕셔너리 안의 값 접근 가능
  • 딕셔너리 키와 값을 빠르게 꺼낼 수 있음
let blog = {
		owner : "noah",
		url : "noahlogs.tistory.com",
		getPost() {
				console.log("ES6 문법 정리");
		}
};

//기존 할당 방식
let owner = blog['owner']
let owner = blog.owner //동일한 결과
let getPost = blog.getPost()

//비구조 할당 방식
let { owner, getPost } = blog;
console.log(owner)

 

💡
리액트 네이티브에서 가장 많이 사용할 방식!
//비구조 할당 방식
let blogFunction = ({owner,url,getPost}) => {
		console.log(owner)
		console.log(url)
		console.log(getPost())
}
blogFunction(blog)

 

백틱 (`) 사용

  • 줄바꿈을 자유롭게
const message = `줄바꿈
자유롭게 가능`
message //"줄바꿈\n자유롭게 가능"
  • 문자열 안에 변수 넣기
let name="정예원"
let str=`내 이름은 ${name}`
console.log(str) //내 이름은 정예원

 

딕셔너리 구성을 간단하게

  • 변수 이름과 key가 같은 경우
  • 기존에는 딕셔너리 내에서 name:name, job:job으로 썼음
let name="정예원"
let job = "개발자"
let dic={
    name,
    job
}
console.log(dic) //{name: "정예원", job: "개발자"}

 

map

  • 기존 코드
//기존 코드
let numbers = [1,2,3,4,5,6,7]
for(let i=0; i<numbers.length; i++){
		console.log(numbers[i])
}

→ 리스트 길이 값을 알아야 for문 사용 가능

 

  • map 활용
let numbers = [1,2,3,4,5,6,7]
numbers.map((value,i) => {
		console.log(value,i)
})

//위와 동일한 코드
numbers.map(function(value,i){
		console.log(value,i)
}
💡
value : 값 i : 인덱스 (순서)

 

JS 파일 모듈화

  • export : 자바스크립트 값, 함수, 딕셔너리, JS 파일 자체를 외부로 내보내기
  • import : JS 파일로 불러오기
//util.js 파일

export function times(x){
		return x*x
}
export function plusTwo(number){
		return number + 2
}
//index.js 파일

import {times, plusTwo} from './util.js'
console.log(times(2))
console.log(plusTwo(3))

 

  • export default
💡
export default는 하나의 파일 안에서 유일해야함
//util.js 파일
export default function times(x){
		return x*x
}
//app.js 파일
import k from './util.js'
console.log(k(4)) //16

 

Uploaded by Notion2Tistory v1.1.0


지금까지 "리액트"라는 것을 들어보긴 했으나 내가 직접 다루고 공부한 적은 없었다.

오늘부터 수강하게 된 앱개발 종합반에서는 리액트 네이티브 앱 개발을 배울 것이다.

 

리액트 네이티브란, 안드로이드와 iOS 두 개의 운영체제에서 모두 실행될 수 있는 크로스 플랫폼 앱 개발 언어 중 하나이며,
이번 주에는 리액트를 본격적으로 다루기 전에
리액트의 기반 언어인 자바스크립트의 기초를 배우는 시간을 가졌다.

자바스크립트의 리스트, 딕셔너리 구조와 이 둘의 복합 구조를 사용하는 방법을 알게 되었고
JSON 데이터 구조가 리스트와 딕셔너리의 복합 구조라는 사실을 알게 되어
JSON이라는 내가 알지 못하던 것에 대한 거부감(?)이 사라진 듯 하다.

튜터님이 차근차근 잘 알려주셔서 그런듯!👍

그리고 앱 개발 시 자주 쓰인다고 하는 화살표 함수, 비구조 할당 방식, map 등을 배워서 좋았다~

+ Recent posts