728x90
반응형

AsyncStorage란?

웹에서 로컬 스토리지랑 비슷한 앱 내부에서 저장하는 라이브러리가

바로 그 것입니다

 

이 라이브러리를 사용하게 되면

로그인 후 앱을 꺼지고 나서도

로그인을 유지할 수 있도록 하는 기능입니다

 

 

React Native 사용 설치와 Expo 설치는 아래와 같이 하시길 바랍니다

yarn add @react-native-async-storage/async-storage
expo install @react-native-async-storage/async-storage

 

 

우선 로그인 기능에 

AsyncStorage함수를 사용하여

로그인 후 로컬 스토리지에 저장합니다

 

 

import * as firebase from "firebase";
import "firebase/firestore";
import { Alert } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { confirmAlert } from '../item/alertPopup'

export async function registration(nickName, email, password, navigation) {
  try {
    console.log(nickName, email, password);
    await firebase.auth().createUserWithEmailAndPassword(email, password);
    const currentUser = firebase.auth().currentUser;
    const db = firebase.firestore();
    db.collection('users').doc(currentUser.uid).set({
      email: currentUser.email,
      nickName: nickName,
    });
    Alert.alert('회원가입 성공!');
    await AsyncStorage.setItem('session', email);
    navigation.push('TabNavigator');
  } catch (err) {
    Alert.alert('무슨 문제가 있는 것 같아요! => ', err.message);
  }
}

export async function signIn(email, password, navigation) {
  try {
    await firebase.auth().signInWithEmailAndPassword(email, password);
    await AsyncStorage.setItem('session', email);
    navigation.push('TabNavigator');
  } catch (err) {
    Alert.alert('로그인에 문제가 있습니다! ', err.message);
  }
}

export function logout(navigation) {
  try {
    confirmAlert('로그아웃을 진행하시겠습니까?', async () => {
      const currentUser = firebase.auth().currentUser;
      console.log(currentUser)
      await AsyncStorage.removeItem('session');
      await firebase.auth().signOut();
      navigation.push("SignInPage")
    })
  } catch (err) {
    Alert.alert('로그 아웃에 문제가 있습니다! ', err.message);
  }
}

 

위와 같이 로그인과 로그아웃, 회원 가입할 경우

로컬 스토리지에 저장을 하게 됩니다 

 

아래는 함수의 사용법을 입니다

 

 

 

반응형

 

 

 

로컬 스토리지에서 특정값 가져오기

AsyncStorage.getItem('session', (err, result) => {
  console.log(result);
})

 

 

로컬스토리지에서 특정값 저장하기

AsyncStorage.setItem('session', email, ()=>{
  console.log('저장 완료')
});

 

 

로컬스토리지에서 특정값 삭제하기

AsyncStorage.removeItem('session');

 

 

하지만 이 라이브러리는 

약간의 단점이 존재한다

AsyncStorage는 저장할 당시 

String값의 Key-Value 체인으로 되어있기 때문에

JSON이나 Array와 같은 형식의 데이터를 저장하는데 

JSON.parseJSON.stringifyObject형식으로 변경하여 저장해야 합니다

 

 

AsyncStorage.setItem('session',JSON.stringify({'email': 'https://tantangerine.tistory.com/' }), () => {
  console.log('저장 완료')
});

AsyncStorage.getItem('session', (err, result) => {
  const MbInfo = Json.parse(result);
  console.log('email : ' + MbInfo.email);
});

 

 

위와 같이 데이터를 저장하고 가져와야 합니다

 

조금 불편 하지만 위의 코드를 함수모듈화로 

보다 쉽게 사용할 수 있을 것입니다

 

 


// AsyncStorage getItem 함수
export const getItemFromAsync = (storageName) => {
  let resultData
  AsyncStorage.getItem(storageName , (err, result) => {
    resultData = JSON.parse(result)
  });
  
  return resultData
};

// AsyncStorage setItem 함수 
export const setItemToAsync = (storageName, item) => {
  let isSuccess = false
  AsyncStorage.setItem((storageName, ,JSON.stringify(item)), (error) => {
    if(error){
      return isSuccess 
    }
  });
   return isSuccess
};

 

 

조금 엉성하지만 위와 같이 만들어 보았습니다

앱에서도 로컬 스토리지에 저장할 수 있는 방법을 알아보았습니다

 

 IT 개발자로 당당해지는 그날까지 계속 나아갑시다

대모험은 아직 끝나지 않았으니까요!!

그럼 열공하시고!

 

다음 포스팅은 파이어 베이스의 Cloud Firestore에 대해

데이터 저장 읽기 이미지 저장 등을 알아보겠습니다

 

한걸음 나아갑시다!!

 

 

728x90
반응형
728x90
반응형

저번 포스팅에서 

Authentication & Cloud Firestore

서버 및 기능 구현을 완료하였습니다

 

2022.07.20 - [Server/Firebase] - React Native X Expo X 파이어 베이스 Authentication 및 Cloud Firestore 서버 구축

 

React Native X Expo X 파이어 베이스 Authentication 및 Cloud Firestore 서버 구축

Authentication이란? 이 서비스는 다양한 타 앱들의 정보로 계정 인증하여 보다 손쉽게 회원가입과 로그인을 구현할 수 있습니다. 그리고 타 앱 간의 정보 인증 이외에도 휴대폰 번호와 이메일 인증

tantangerine.tistory.com

 

 


 

회원가입 구현하기

firebase의 인증 기능을 사용하기 위해 

파이어 베이스의 함수를 호출해서 결과값을 받아 인증 및  회원가입을 진행하게 됩니다.

이때 고객의 기입정보를 데이터 베이스에 저장하며

인증 테이블에 고유키 값과 비밀번호도 저장하게 됩니다.

 

직관적으로 관리하기위해

firebaseApi.js 파일을 만들고 아래와 같이 코드 작성을 해서 

필요할 때 import 하여 사용합니다.

 

 

회원가입 폼 이미지

 

 

회원가입 폼에서 등록버튼을 누르면

registration() 함수를 호출하여

아래와 같은 함수를 실행하게 됩니다

 

 

import * as firebase from "firebase";
import "firebase/firestore";
import {
  Alert
} from "react-native";

export async function registration(nickName, email, password, navigation) {
  try {
    console.log(nickName, email, password)
    await firebase.auth().createUserWithEmailAndPassword(email, password);
    const currentUser = firebase.auth().currentUser;
    const db = firebase.firestore();
    db.collection("users")
      .doc(currentUser.uid)
      .set({
        email: currentUser.email,
        nickName: nickName
      });
    Alert.alert("회원가입 성공!")
    navigation.push("TabNavigator")

  } catch (err) {
    Alert.alert("무슨 문제가 있는 것 같아요! => ", err.message);
  }
}

 

 

회원가입을 진행하면 

firebase.auth().createUserWithEmailAndPassword(); 함수를 사용해서 

기입한 메일과 uid의 고유번호를 생성해서 식별자 테이블에 정보를 저장하게 됩니다

 

이때 중요한 것은 비동기(async/await)가 정말 중요합니다

회원가입이 끝날 때까지 다른 작업은 안 하는 것이 좋겠지요?

 

그리고 firebase.auth().currentUser 함수를 사용하게 되면

현재 자신의 uidemail 정보를 조회할 수 있습니다.

 

또한, 그 정보를 가지고 데이터베이스에 컬렉션의 상위는 usersuid를 저장합니다

그리고 emailnickName을 같이 지정하여 저장합니다.

 

 

 

식별자 데이터 생성 함수와 데이터 베이스에 저장하는 함수

 

 

 

위의 함수를 실행하게 되면 아래와 같이 저장됩니다

아래에 식별자는 자신의 이메일이 저장이 됩니다

사용자 uid는 고유한 키값으로 파이어 베이스에서 생성해줍니다

 

 

 

 

반응형

 

 

 

식별자 테이블에 정보가 저장된다

 

 

컬렉션의 user와 문서는 사용자 uid가 저장되며 필드는 

회원의 정보가 저장된 것을 확인할 수 있습니다

 

 

 

데이터 정보

 

 

 

위의 정보는 아래의 코드로 표현할 수 있습니다

 

 

 

{
    users : {
        IkafkITYpGXfYlxLsqU1W2uD2XC2 : {
            email : "sparta@gmail.com",
            nickName: "Gunhee"
        }
    }
}

 

 

 

로그인 구현하기

로그인 폼에서 아래와 같은 함수를 실행해서 

firebase.auth().signInWithEmailAndPassword(); 함수를 

호출해서 기입한 정보들이 현재 식별자 테이블에 있는지 확인을 합니다

 

로그인에 성공하면 탭 내비게이션 메인 페이지로 이동하게 됩니다

 

 

 

export async function signIn(email, password, navigation) {
  try {

    await firebase.auth().signInWithEmailAndPassword(email, password)
    navigation.push("TabNavigator")

  } catch (err) {
    Alert.alert('로그인에 문제가 있습니다! ', err.message);
  }
}

 

 

이렇게 회원가입 및 로그인 기능을 구현하였습니다

구글 파이어 베이스를 사용하면

정말 간편하게 구현할 수 있었습니다

 

이렇게 한 개씩 하다 보면 조금도 숙달이 되겠지요?

비동기 부분도 한 번씩 더 보고 더 깊게 공부를 해보아야겠다는

생각하게 되었습니다.

 

그럼 오늘도 파이팅 하시고~!

즐거운 대모험이 되시길 바랍니다!!

 

파이팅!!

728x90
반응형
728x90
반응형

Authentication이란?

이 서비스는 다양한 타 앱들의 정보로 계정 인증하여 보다 손쉽게

회원가입과 로그인을 구현할 수 있습니다.

 

그리고

타 앱 간의 정보 인증 이외에도 휴대폰 번호와 이메일 인증으로도

구현이 가능합니다.

 

이 기능을 사용하기 앞서 우선 

가장 중요한 데이터베이스를 구성해야 합니다

그래야 지만 회원가입의 유저 정보를 저장할 수 있습니다

 

그 데이터베이스를 구축하기 위해서는 

Cloud Firestore를  사용해보도록 하겠습니다

 

잠깐

저번에 배운 리얼타임 데이터 베이스와 또 다른 것입니다

같은 firebase의 데이터 베이스지만 서로 다른 기능들을 가지고 있습니다

 

2022.07.08 - [Server/Firebase] - React Native X Expo X 파이어 베이스 리얼타임 데이터 베이스 설정 및 조회, 추가, 삭제 기능 구현

 

React Native X Expo X 파이어 베이스 리얼타임 데이터 베이스 설정 및 조회, 추가, 삭제 기능 구현

리얼 타임 데이터 베이스란? 플랫폼과 실시간 데이터를 송신할 수 있는 기능이라고 생각하시면 됩니다 그리고 기능을 사용하기 위해서는 파이어 베이스가 가지고 있는 고유한 기능들을 사용하

tantangerine.tistory.com

 

두 가지의 차이점은 다음 포스팅 때 알아보도록 하고

우선 지금 구축할 데이터 베이스를 알아보도록 하겠습니다

 

 

 


 

 

 

Cloud Firestore이란?

리얼 타임 데이터베이스보다 확장성이 크며 직관적이 모델링과

풍부하고 빠른 쿼리와 원활한 확장성을 제공하고 있습니다

 

리얼타임 데이터베이스의 업그레이드 버전이라고 생각하시면 되겠습니다

하지만 꼭 그런 개념은 아니니 다음 포스팅 때 알아보도록 해요

 

 

우선 아래의 같이 폴더와 파일을 생성해줍니다

프로젝트를 생성하여 키값을 파일로 관리를 하기 위함입니다

 

일단 파이어 베이스 프로젝트를 추가하시지 않았다면 위의 포스팅에 들어가시면 프로젝트 추가 방법과

키값의 위치를 확인할 수 있습니다

 

 

그리고 Expo파이어 베이스구축하려고 하니 설치는 필수입니다!

expo install firebase

 

생성된 키값을 복사해서 

아래 와같이 파일을 생성합니다

 

폴더 및 파일 생성 키값설정

 

아래의 이미지처럼 export default를 해서 

여러 파일에서 사용할 수 있게 만들어 줍니다

 

 

키값 설정 이미지

 

그리고 마지막으로 데이터 베스 이를 만들기로 합시다

 

데이터베이스 만들기 Cloud Firestore

 

Cloud Firestore 만들기

 

 

파이어 베이스로 로그인하여 프로젝트 시작하면

대시보드의 빌드란에 Cloud Firestore가 존재하는 것을 확인할 수 있습니다

데이터 베이스 만들기 버튼을 클릭해서 진행해 봅시다

 

 

 

데이터베이스 보안규칙

 

 

프로덕션 모드로 진행하고

보안 규칙은 추후에 변경하도록 합니다

 

 

 

 

 

위치 설정은 aisia-northest2로 해주며 사용 설정 버튼을 클릭합니다

 

그럼 이제 보안 규칙을 변경하도록 하겠습니다

Cloud Firestroe에 들어가시면 규칙 탭을 확인하실 수 있을 겁니다

 

write 부분을 true로 변경해 줍니다

 

 

규칙 수정

 

 

 

 

이제 데이터 베이스 서버 구축이 완료되었습니다

그럼 서버와 앱을 연결합니다

 

 

app.js 일부분

 

 

위 와같이 import 하여 라이브러리와 접속에 사용할 키값을 가져옵니다

그렇게 firebase.initializeApp() 함수를 사용하여 연결합니다

 

 


 

 

반응형

 

 


 

Authentication 서비스 이용하기

 

위에서 언급했듯이 회원가입 기능과 로그인 기능을 구현하기 위해 필요한 서비스입니다

여러 타 앱들로 계정을 인증받아 정보를 데이터 베이스에 저장하며

Authentication는 고객들의 고유키를 저장하여

관리하는 기능으로 대시보드에서 어드민 페이지가 없이도 데이터 관리가 용이합니다

 

authentication 서비브 시작하기

 

 

그럼 시작하기 버튼을 클릭하여 서비스 이용할 준비를 하겠습니다

아래와 같이 로그인 제공업체 리스트를 볼 수 있으며

새로운 업체들도 추가할 수 있습니다

 

로그인 제공업체

 

 

아래의 제공업체를 클릭하면

2 단계 창이 노출되며 

여러 가지 정보들을 활용하여

업체 간의 인증서비스를 연동시킬 수 있습니다

 

 

 

로그인 제공업체 추가

 

 

아래와 같이 앱 ID와 비밀번호를 입력하여 진행하며

비밀번호 밑에 회색으로 고유 키값이 존재합니다

업체들 간의 데이터인증을 위한 키값이며 

업체들간의 방법과 키값은 모두 다르니

한번 사용 설정해서 어떻게 인증서비스를 이용하는지

이용해보는 것도 좋은 공부가 될 것입니다

 

 

새로운 로그인 제공업체 2

 

 

 

이렇게 서비스를 이용할 모든 준비는 끝이 났습니다

그럼 다음 포스팅에는 이 두 가지 서비스를 이용하여 

회원가입 시 데이터베이스에 고객의 정보를 저장하고

authentication에는 회원의 고유 키값과 비밀번호를 저장함으로써

회원 가입과 로그인 기능을 구현해보겠습니다

 

그럼 오늘 복습도 끝이 났습니다

하루에 2~3시간씩 공부를 하면

힘이 들지만 그래도 앞으로 조금씩 나아간다는 느낌이 확실히 있습니다

내년 말까지는 나만의 앱을 만들기 위해 노력해 보도록 하겠습니다

 

아직 대모험은 끝나지않았다는 것을 명심하시고!

같이 끝가지 나아가요!!

 

 

728x90
반응형
728x90
반응형

Admob(애드몹)이란?

앱에서 구글의 광고를 간편하게 노출할 수 있으며,

그에 따른 수익 현황 및 관리를 도와주는 서비스입니다

 

구글에는 4가지의 광고 모델이 있습니다

 

구글 애드몹 광고 유형

 

 

 

배너

앱 레이아웃의 일부를 차지하는 사각형 광고입니다

 

 

전면

레벨 완료 등의 자연스러운 중단이나 전환시점에 게재되는 전체 페이지 광고 형식입니다

 

 

리워드

광고를 본 사용자에게 리워드를 제공하는 광고 형식입니다

 

 

네이티브 고급 광고

앱의 디자인과 분위기에 어울리게 맞춤설정할 수 있는 광고 형식입니다

 

 

 

 Expo에서도 구글 애드몹 사용이가능합니다

아래와 같이 라이브러리를 추가합니다

 

 

expo install expo-ads-admob

 

 

라이브러리를 추가 완료하면,

아래의 코드를  app.json 파일 하단부에 추가합니다

그러면 사용할 준비

 

"ios": {
      "supportsTablet": true,
      "buildNumber": "1.0.0",
      "bundleIdentifier": "##########",
      "config": {
        "googleMobileAdsAppId": ""
      }
    },
    "android": {
          "package": "##########",
          "versionCode": 1,
          "config": {
            "googleMobileAdsAppId": ""
          }
  },

 

 

 

bundleIdentifier, package는 앱 마켓들과 구글에 앱 이름을 알려주는 부분입니다.

설정은 이렇게 끝을 내고 광고 배너 생성을 알아보자

 

 

구글 광고 애드몹(AdMob) 가로 배너 생성

 

 

광고 4가지 유형에서 선택하면, 

광고 단위 설정 구성화면에서 광고 단위 이름을 지정하고 

광고 단위 만들기 버튼을 클릭해서 광고를 생성한다

 

광고 설정 화면

 

 

아래와 같이 키값이 형성되고

그 키값들은 app.json에 설정하여야 합니다

 

 

광고 생성화면

 

 

 

래의 키값은

app.json에 비워져 있던 androidgoogleMobileAdsAppId에 적용합니다

 

 

 

광고 SDK

 

 

 

아래의 키값은 

AdMobBanner 컴포넌트의 adUnitId 속성에 적용합니다

 

 

 

광고 유닛키

 

 

아래와 같이 코드를 작성하면 제일 하단에 광고가 노출될 수 있습니다

여러 속성들은 사이드바에 Expo 애드몹 공식문서를 참조하세요

 

 

{Platform.OS === 'ios' ? (
                <AdMobBanner
                  bannerSize="fullBanner"
                  servePersonalizedAds={true}
                  adUnitID="ca-app-pub-3271224099084995/4041258226"
                  onDidFailToReceiveAdWithError={bannerError}
                  style={styles.banner}
                />
            ) : (
                <AdMobBanner
                  bannerSize="fullBanner"
                  servePersonalizedAds={true}
                  adUnitID="ca-app-pub-3271224099084995/5120026862"
                  onDidFailToReceiveAdWithError={bannerError}
                  style={styles.banner}
                />
            )}

 

 

AdMobBanner 컴포넌트는 아래와 같이 속성을 가지고 있습니다

 

 

banner 휴대폰 및 태블릿용 표준 배너 320x50
largeBanner 휴대폰 및 태블릿용 대형 배너 320x100
mediumRectangle 휴대폰 및 태블릿용 IAB 중간 직사각형 300x250
fullBanner 태블릿용 IAB 전체 크기 배너 468x60
leaderboard 태블릿용 IAB 리더보드 728x90
smartBannerPortrait 휴대폰 및 태블릿용 스마트 배너(기본값) 화면 너비 x 32
smartBannerLandscape 휴대폰 및 태블릿용 스마트 배너 화면 너비 x 32

 

 

광고 단위 생성은 

전면, 리워드, 네이티브 고급 광고도 위와 같이 생성하여

두 개의 키값을 사용하면 됩니다.

 

 

구글 광고 애드몹(AdMob) 전면 배너 생성

전면 광고를 사용자들에게 아래와 같이 노출하는 광고를 생성합시다

 

전면 광고 노출

 

 

아래의 코드를 작성하면 

꿀팁인 카드 컴포넌트를 클릭하면 전면광고가 뜨고

전면 광고 노출 일정 시간 후 디테일 페이지로 이동하게 됩니다

 

그리고 ios와 안드로이드의 분기를 하여 키값을 따로 설정해줍니다

그리고 로드를 시작할 때 함수와 로드를 끝날때 함수와 광고 시작할때 함수 광고가 끝날대 함수를 설정해서

광고가 끝나거나 시작할때 어떠한 함수를 실행할 수 있습니다

 

가장 중요한 것은 애드몹도 외부 API 이므로 실행 순서를

지키기 위해 async/await 사용해야 한다는 것입니다

 

import React, { useEffect } from 'react';
import {View, Image, Text, StyleSheet,TouchableOpacity,Platform} from 'react-native'
import {
  setTestDeviceIDAsync,
  AdMobBanner,
  AdMobInterstitial,
  PublisherBanner,
  AdMobRewarded
} from 'expo-ads-admob';

export default function Card({content,navigation}){

    useEffect(()=>{
        Platform.OS === 'ios' 
            ? AdMobInterstitial.setAdUnitID("ca-app-pub-5579008343368676/6838730428") 
            : AdMobInterstitial.setAdUnitID("ca-app-pub-5579008343368676/4903859898")

        AdMobInterstitial.addEventListener("interstitialDidLoad", () =>
            console.log("interstitialDidLoad")
        );
        AdMobInterstitial.addEventListener("interstitialDidFailToLoad", () =>
            console.log("interstitialDidFailToLoad")
        );
        AdMobInterstitial.addEventListener("interstitialDidOpen", () =>
            console.log("interstitialDidOpen")
        );
        AdMobInterstitial.addEventListener("interstitialDidClose", () => {
            console.log("interstitialDidClose")
          
        });
    },[])
    const goDetail = async () =>{
      try {
        await AdMobInterstitial.requestAdAsync({ servePersonalizedAds: true});
        await AdMobInterstitial.showAdAsync();
        await navigation.navigate('DetailPage',{idx:content.idx})
      } catch (error) {
        console.log(error)
        await navigation.navigate('DetailPage',{idx:content.idx})
      }
    }

    return(
        <TouchableOpacity style={styles.card} onPress={()=>{goDetail()}}>
            <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>
        </TouchableOpacity>
    )
}

 

 

 

setAdUnitID, requestAdAsync, showAdAsync 등의 함수는 아래와 같이 설명을 확인할 수 있습니다

 

그리고 광고 노출 전 키값을 먼저 세팅하고 함수들을 지정함으로써

광고 상태로 함수를 실행할 수 있습니다

 

그 후 detailPage로 이동하는 함수에 requestAdAsync 함수와 showAdAsync를 사용하여

전면광고를 노출합니다

 

다시 말하지만 비동기가 중요합니다!!

 

그리고 useEffect인 화면 첫 랜더링 시 실행하는 함수들을 나열하는 것 또한 중요합니다!!

 

 

 

이렇게 구글의 애드몹 광고 배너와 전면광고 노출하는 방법을 알아보았습니다

다음에는 시간이 있다면 다른 광고들도 한번 알아보도록 하겠습니다

 

그럼!

 

 

 

 

 

 

 

 

 

 

728x90
반응형
728x90
반응형

탭 네비게이션 활용 및 설정 법은 이전 글 포스팅으로 확인하세요

 

 

2022.07.17 - [Mobile/React Native] - 리액트 네이티브 X EXPO 탭 네비게이터 설정 및 TabNavigator 사용방법을 알아보자

 

리액트 네이티브 X EXPO 탭 네비게이터 설정 및 TabNavigator 사용방법을 알아보자

탭 내비게이터란? 여러 앱들이 아래의 UI를 많이 채택해서 사용하고 있습니다 탭이라는 하단 영역에 직관적인 아이콘을 사용함으로써 페이지 이동을 보다 자유롭게 하게 함입니다 스택 내비게

tantangerine.tistory.com

 

 

 

메인 페이지에는 많은 이미지들이 존재합니다

이처럼 이미지가 많은 페이지라면 이미지가 지연없이 부드럽게 호출할 수 있게

react-native-image-blur-loading 라이브러리를 사용하도록 하겠습니다

 

 

라이브러리를 다음과 같이 추가합니다

 

yarn add react-native-image-blur-loading

 

 


 

 

메인페이지 구성 및 배너카드 구성하기

 

 

mainPage를 아래와 같이 코드를 작성합니다

메인페이지에 Grid 컴포넌트를 사용해서 메인에서 한개의 배너카드를 구현할 수 있습니다

이렇게 로고 배너를 삽입하여 어떠한 정보를 노출할 수 있습니다

CardComponent에 적용하는 것이 아니라

메인에 적용하여 단발적인 배너카드만 적용하게된다

 

 

배너 카드

 

 

 

import React from 'react';
import { StyleSheet, View } from 'react-native';
import { Col, Grid } from 'react-native-easy-grid';
import { Container, Content, Icon, Text } from 'native-base';
import CardComponent from '../components/CardComponent';
import HeaderComponent from '../components/HeaderComponent';

const data = require('../data2.json');
export default function MainPage({ navigation }) {
  return (
    <Container>
      <HeaderComponent />
      <Content>
        <Grid style={styles.banner}>
          <Col size={1} style={{ padding: 20 }}>
            <Icon name="paper-plane" style={{ color: 'deeppink' }} />
          </Col>
          <Col size={6} style={{ padding: 15 }}>
            <Text>이야기 하고 싶은 친구들에게</Text>
            <Text style={{ fontWeight: '700' }}>wegram을 전하세요</Text>
          </Col>
        </Grid>
        <Grid style={{ padding: 20 }}>
          <Text style={{ color: 'grey' }}>FROM THE DIARY</Text>
        </Grid>
        <View style={{ marginTop: -20 }}>
          {data?.diary?.map((content, i) => {
            return (
              <CardComponent
                content={content}
                key={i}
                navigation={navigation}
              />
            );
          })}
        </View>
      </Content>
    </Container>
  );
}

const styles = StyleSheet.create({
  banner: {
    backgroundColor: '#F6F6F6',
    height: 70,
    borderRadius: 10,
    width: '90%',
    alignSelf: 'center',
  },
});

 

구조는 네이티브 베이스를 사용해서 Grid, Col 사용한것을 확인 할수 있습니다.

 

또 한,

CardComponent, HeaderComponent를사용하여 아래와 같이 구현하게됩니다.

 

메인페이지 이미지

 

헤더컴포넌트에 대한 코드는 아래와 같습니다.

 

 

네이티비 베이스의 Header컴포넌트를 사용하여

transparent의 속성을 부여하여 배경색을 제거합니다.

 

여기에서 중요 포인트는 Left, Right를 사용하여 

왼쪽에는 로고와 오른쪽에는 토글이미지의 설정기능할 수 있는 영역을 지정합니다

이것으로 HeaderComponent 구성은 쉽게 끝낼 수 있습니다.

 

 

 

반응형

 

 


 

HeaderComponent  구성하기

 

 

헤더 이미지

 

import React from 'react';
import { StyleSheet, Image, View } from 'react-native';
import { Header, Left, Icon, Right, Text, Button } from 'native-base';

const logo = require('../assets/logo.png');

export default function HeaderComponent() {
  return (
    <Header transparent>
      <Left>
        <Button transparent>
          <Image source={logo} style={styles.logoImage} />
        </Button>
      </Left>
      <Right>
        <Icon name="ellipsis-horizontal" style={{ color: 'deeppink' }} />
      </Right>
    </Header>
  );
}

const styles = StyleSheet.create({
  logoImage: { width: 100, resizeMode: 'contain', marginLeft: 10 },
});

 

 

 

위의 코드는 HeaderComponent 입니다.

 

 


 

CardComponent 구성 및 ImageBlurLoading 구성하기

 

 

CardComponent는 위에 설명했듯이

ImageBlurLoading 컴포넌트를 사용하였습니다

이미지를 부드럽게 호출할 수 있는 라이브러리 입니다

 

ImageBlurLoading 속성에

thumbnailSource는 이미지가 로딩될때 보여지는 이미지를 출력합니다

withIndicator는 이미지로딩시 로딩중이라고 알려주는 기능입니다

source는 이미지 데이터입니다

이때 ImageBlurLoading 컴포넌트는 CardItem에 사용하여 한개의 이미지를 컴포넌트로 생각한다

 

그리고 CarItemCard에서 CarItem을 사용하여 영역을 지정하여

편리하게 이미지를 구현할 수 있습니다

 

 

import React from 'react';
import { StyleSheet, Image, TouchableOpacity } from 'react-native';
import { Col, Row, Grid } from 'react-native-easy-grid';
import { Icon, Text, Card, CardItem } from 'native-base';
const image = require('../assets/background2.png');
const logo = require('../assets/logo.png');
import ImageBlurLoading from 'react-native-image-blur-loading';

export default function CardComponent({ navigation, content }) {
  return (
    <TouchableOpacity
      onPress={() => {
        navigation.navigate('NewDetailPage', { content: content });
      }}
      style={styles.container}
    >
      <Card style={styles.card} transparent>
        <CardItem transparent>
          <ImageBlurLoading
            withIndicator
            thumbnailSource={{ uri: content?.image }}
            source={{ uri: content?.image }}
            style={styles.image}
          />
        </CardItem>
        <CardItem style={{ marginTop: -10 }}>
          <Grid>
            <Col size={9}>
              <Text numberOfLines={1} style={styles.title}>
                {content.title}
              </Text>
              <Text style={[styles.grey, styles.writer]}>{content.author}</Text>
            </Col>
            <Col size={2}>
              <Grid>
                <Col>
                  <Icon name="chatbox-outline" style={styles.grey} />
                </Col>
                <Col>
                  <Icon name="heart-outline" style={styles.grey} />
                </Col>
              </Grid>
            </Col>
          </Grid>
        </CardItem>
      </Card>
    </TouchableOpacity>
  );
}

const styles = StyleSheet.create({
  container: { alignItems: 'center', alignSelf: 'center' },
  card: {
    width: '100%',
    alignSelf: 'center',
  },
  image: { height: 200, width: '100%', borderRadius: 10 },
  grey: { color: 'grey' },
  writer: { fontSize: 12, color: 'grey', marginLeft: 10 },
  title: { fontWeight: '700', fontSize: 15, marginLeft: 10 },
});

 


 

 

 

이렇게 메인페이지를 구현해보았습니다

이번에는 CardComponentImageBlurLoadingCarItem을 활용하였습니다

CarItem은 사이드 메뉴의 Expo의 공식문서를 보면서 더욱 활용도를 높여보세요

 

언제나 배우면 배울수록 끝이 없는것같다고 생각이 드네요

화이팅 하시고 힘내세요!!

 

아직 우리의 IT대모험은 끝나지 않았으니까요!!

파이팅!

 

 

 

728x90
반응형
728x90
반응형

 

탭 내비게이터란?

 

여러 앱들이 아래의 UI를 많이 채택해서 사용하고 있습니다

탭이라는 하단 영역에 직관적인 아이콘을 사용함으로써

페이지 이동을 보다 자유롭게 하게 함입니다

 

스택 내비게이터와 비슷하며 두 개를 같이 사용한다고만 알고 계시고 

예문을 보면서 같이 알아보도록 하겠습니다

 

 

 

2022.07.04 - [Mobile/React Native] - React Native_스택 내비게이션 활용 페이지와 컴포넌트 이동

 

React Native_스택 네비게이션 활용 페이지와 컴포넌트 이동

스택 네비게이션이란? 컴포넌트에서 컴포넌트로 이동을 용이하게 해주는 기능이다. 즉 페이지를 이동하는 방법이라고 생각하면된다. 컴포넌트를 이동이라고는 하지만 솔직히 페이지 이동이라

tantangerine.tistory.com

 

 

탭 네비게이터 설정방법

 

 

페이지 구성

 

마이페이지와 그리고 메인 페이지, 팁 페이지, 페이지를 추가할 페이지를 

만들어 보겠습니다

 

 

탭 네비게이터 영역의 아이콘 노출이미지

 

 

 

각각 영역을 선택하게 되면 아래와 같은 페이지가 노출되게 연결하겠습니다

 

 

구현 할 페이지 이미지

 

 

탭 내비게이터 영역에 들어갈 페이지를 컴포넌트로 탭 내비게이터와 연결합니다

 

 

탭 네비게이터 라이브러리 추가

 

아래와 같이 라이브러리를 추가하여 줍니다.

 

yarn add @react-navigation/bottom-tabs

 

 

TabNavigator.js 파일을 생성하고 

아래와 같이 코드 작성을 합니다

 

 

탭 네비게이터 코드 작성

 

import React, { useEffect } from 'react';

import { Platform } from 'react-native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

import TipPage from '../pages/TipPage';
import MainPage from '../pages/MainPage';
import MyPage from '../pages/MyPage';
import AddPage from '../pages/AddPage';
import { Ionicons } from '@expo/vector-icons';

const Tabs = createBottomTabNavigator();

const TabNavigator = ({ navigation, route }) => {
  return (
    <Tabs.Navigator
      screenOptions={({ route }) => ({
        tabBarShowLabel: true,
        tabBarStyle: {
          backgroundColor: '#fff',
          borderTopColor: '#eee',
          height: 40,
          fontSize: 10,
        },
        tabBarIcon: ({ focused }) => {
          let iconName = Platform.OS === 'ios' ? 'ios-' : 'md-';

          if (route.name === 'MainPage' || route.name === 'TipPage') {
            iconName += 'list';
          } else if (route.name === 'AddPage') {
            iconName += 'apps-outline';
          } else if (route.name === 'MyPage') {
            iconName += 'person';
          }
          return (
            <Ionicons
              name={iconName}
              color={focused ? 'hotpink' : 'grey'}
              size={26}
            />
          );
        },
      })}

    >
      <Tabs.Screen name="MyPage" component={MyPage} />
      <Tabs.Screen name="MainPage" component={MainPage} />
      <Tabs.Screen name="TipPage" component={TipPage} />
      <Tabs.Screen name="AddPage" component={AddPage} />
    </Tabs.Navigator>
  );
};

export default TabNavigator;

 

 

위의 코드를 보시면 화면 아래 탭 영역에 추가할 페이지를 컴포넌트 속성에 할당합니다

그러면 아래 탭 영역에는 4개의 아이콘이 노출되는 것을 확인할 수 있습니다

 

 

그리고 위의 아이콘들은 Expo에서 제공하는 아이콘들입니다

 

 

Expo 아이콘 활용하기

라이브러리를 아래와 같이 추가하시면 사용이 가능합니다

 

 

expo install expo-font

 

 

라이브러리를 사용하는데 약간의 규칙이 있습니다

아래의 부분을 보시면

Palatform.os의 함수를 사용하면 ios인지 안드로이드 인지 구분을 할 수 있는 값을 return 합니다

그 값을 활용해서 사용할 아이콘의 이름을 플랫폼별 다른 값을 더해 노출할 수 있습니다 

 

그리고 focused를 통해 클릭할 당시의 색깔을 변경할 수 있습니다

 

 

 

 

반응형

 

 

 

탭 네비게이션의 속성 활용법

 

 

플렛폼별 아이콘 설정법

 

 

또한,

공식문서를 보면 더 많은 아이콘들을 확인할 수 있습니다

그리고 공식 문서는 사이드 메뉴에 라이브러리 공식문서 칸에 등록해놓겠습니다

 

 

전체 방문자 밑에 있으니 클릭해서 보세요

 

 

expo 공식문서 소개

 

 

그리고!

screenOptions에 여러 가지 속성을 부여할 수 있다

경우에 맞게 속성을 부여해 봅시다~

 

  • tabBarActiveTinitColor : 활성화된 항목의 아이콘과 텍스트 색상
  • tabBarActiveBackgroundColor : 활성화된 항목의 배경색
  • tabBarInactiveTintColor : 비활성화된 항목의 아이콘과 텍스트 색상
  • tabBarInactiveBackgroundColor : 비활성화된 항목의 배경색
  • tabBarShowLabel : 항목에서 텍스트의 가시성 설정(default : true)
  • tabBarShowIcon : 항목에서 아이콘의 가시성 설정(default : false)
  • tabBarStyle : 하단 탭 스타일
  • tabBarLabelStyle : 텍스트 스타일
  • tabBarItemStyle : 항목 스타일
  • tabBarLabelPosition : 텍스트 위치
    - beside-icon : 아이콘 우측
    - below-icon : 아이콘 하단
  • tabBarAllowFontScaling : 시스템 폰트 크기에 따라 폰트 크기를 키울지 결정(default : true)
  • tabBarSafeAreaInset : SafeAreaView의 forceInset 덮어쓰는 객체(default: {bottom: 'always', top: 'naver'})
  • tabBarKeyBoardHidesTabBar : 키보드가 나타날 때 하단 탭을 가릴지 결정(default : false)

 

 

 

screenOptions에서 route 값을 활용하고 싶으면

화살표 함수를 이용해서 return으로 통으로 값을 할당할 수 있습니다

그래서 현재 name를 활용해서 플랫폼 별 아이콘을 설정할 수 있습니다

 

 

scrennOption 설정 방법

 

route name 활용

 

 

routefocused 이외에도 여러 속성이 존재합니다

아래와 같이 screenOptions에 있는 속성들을 navigation안에 여러 함수들과

조금 전에 사용한 route를 보실 수 있습니다

 

 

screenOptions 속성

 

 

tabBarIcon에도 여러 가지 속성을 확인하실 수 있습니다

 

tabBarIcon 속성

 

여러 가지를 속성들을 확장연산자를 사용하여 object안에 있는 변수를 바로 사용하는 모습을 볼수 있어요

상황에 맞게 여러가지 속성들을 사용하면 될 것 같습니다

다른 옵션에도 어떠한 속성들이 있는지 확장 연사자를 쓰지 전에 props로 받아서 

console.log()로 확인을 해보시길 바랍니다.

 

 

stackNavigator.js에 상단에 추가해주면 되겠습니다

return의 상단에 하셔야 합니다!!

<Stack.Screen name="TabNavigator" component={TabNavigator} options={{ headerShown: false }}/>

 

 

이것으로 탭 내비게이션의 설정법을 알아보았습니다

다음에는 활용법을 알아보도록 하겠습니다

그런데 너무 길어지지 다음 포스팅에 알아보도록 하겠습니다

 

오늘도 조금 어려운 점이 없지 않았나 하고 생각 드네요

그래도 새로운 것을 공부하는 것은 필요하다고 생각합니다

IT 개발자들은 필수이지요!!

 

자체 플랫폼 서비스를 하는 곳에서는

쓰는 언어나 패턴들이 정형화되어 새로운 공부를 하지 않게 되는데

요즘 개발자가 귀한 상황이니 열심히 공부해서 더 좋은 곳으로 이직하는 것도 좋은 방법이겠네요

 

파이팅 하시고 힘들어도 힘내세요!

아직 대모험은 끝나지 않았으니까요!

파이팅!!

 

728x90
반응형
728x90
반응형

오라클에서는 트리구조가 아주 중요합니다

level ~ start with ~ connect by prior ~를 많이 사용합니다

그러나 오라클을 처음 접하는 사람은 이 구문을 한 번에 이해하기가 쉽지 않습니다

그래서 한번 이 구문의 예문을 통해 같이 알아보고자 합니다

 

 

아래와 같이 테이블이 존재합니다

 

SELECT DEPTNO, ENAME FROM EMP

 

 

 

가공 전 데이터

 

위의 데이터로 아래와 같이 출력하고자 합니다

어떤 사람은 case문으로 하면 안 되지 않을까 하고 의문을 갖는 사람도 있을 거라 생각합니다

당연히 가능합니다

하지만 case문은 deptno의 값이 쿼리에 값 조건문이 들어가야 합니다

이러한 경우는 deptno가 증가할 경우에 대해 전혀 대비가 되지 않은 쿼리라고 할 수 있습니다

프로젝트를 진행하다 보면 case문을 자주 사용하게 되는데

그 함정에 빠져 큰 그림을 보지 못하고 당장 앞만 보게 되는 경우가 있습니다

그래서 대도록이면 테이블의 데이터 값이 쿼리문에는 없는 것이 범용성이 좋은 쿼리라고 할 수 있습니다

 

그리고 이러한 재밌는 쿼리를 보면

여러 가지를 생각나게 합니다

밑에 deptno별로 모든 직원을 조회해야 한다면

밑에 처럼 안 하면 java에서 map형 list로 담아서 진행해야 합니다

하지만 아래처럼 한다면 list형 map으로 간단히 담아질 것으로 보입니다

하지만 그렇게 되면 자바에서 또다시 다른 작업을 진행해야 하겠지요

아무튼!!

계속해서 보도록 하겠습니다

 

 

 

최종 데이터

 

 

 

아래의 코드로 출력이 가능합니다

처음 접하면 너무 복잡하고 어려워 보이겠지만

같이 천천히 봅시다

 

 

 

 select deptno,
         ltrim(sys_connect_by_path(ename,','),',') emps
    from (
  select deptno,
         ename,
         row_number() over
                  (partition by deptno order by empno) rn,
         count(*) over
                  (partition by deptno) cnt
   from emp
        )
  where level = cnt
  start with rn = 1
 connect by prior deptno = deptno and prior rn = rn-1;

 

 

 

 

반응형

 

 

우선 서브 쿼리를 단독 실행해서 사원에 대한 소속 부서, 이름 empno 오름차순 정렬로 결과가 노출되고 있습니다

순위에 해당 하는 RN는 트리를 이동하는 목적입니다.

 


 

start with

start with rn = 1이라는 것은 rn이 1일될때마다 새로운 트리를 만들게 됩니다

 

connect by prior

connect by prior deptno = deptno는 자기 자신을 상위 레벨로 지정을 하고

한 조건을 더 붙여서  rn = rn-1로 합니다

이 의미는 자기 이전행을 상위 레벨로 하겠다 라는 것입니다

이렇게 되면 부서별 마지막 사람이 최하위 레벨이 되며

sys_connect_by_path를 사용하여 모든 행의 이름을 한 칼럼에 노출시킬 수 있습니다

 

sys_connect_by_path

데이터를 읽어오는 그 행의 모든 상위 레벨을 나타낼 수 있게 도와주는 함수입니다

읽어오는 그 행이 최상위라면 자기 행의 데이터만 가져오게 될 것이며,

최하위라면 모든 레벨의 데이터를 가져오게 될 것입니다

 

level

connect by prior를 사용하게 되면 트리구조로 그 행의 트리 레벨을 표현할 수 있습니다

그래서 위와 같이  where level = cnt라는 것은

총인원수를 와 같은 레벨만 보여달라는 것으로

deptno 10은 cnt가 3입니다

그래서 아래와 같이 10은 cnt가 3이며 level도 3인 행만 보여달라는 where 절이였습니다

 

 


 

 

where 절인 level 조건부를 제거하여 노출한 데이터

 

 

 

  select deptno,
         ename,
         row_number() over
                  (partition by deptno order by empno) rn,
         count(*) over
                  (partition by deptno) cnt
   from emp

 

 

 

위의 서브 쿼리를 출력할 경우 아래와 같이 노출됩니다

 

서브쿼리만 출력한 데이터

 

 

이렇게 트리구조에 대해서 알아보았습니다

확실히 트리구조는 무척이나 어렵습니다

처음 접하신 분은 이해가 어려울 수도 있을 것 같습니다

하지만 각각 쓰는 구문들이 어떤 역할을 하는지만

정확하게 알고 있다면 다른 사람이 작성한 코드를 분석하는데

많은 도움이 될 것이라 생각합니다

 

힘내시고 화이팅하세요!!

아직 모험은 끝나지않았습니다!!

파이팅!!

 

728x90
반응형
728x90
반응형

 

앱이나 웹을 만들 때 여러 가지 어려움이 있겠지만 그중에 스타일이 아닐까 합니다

화면을 스타일링은 익숙하지 않은 사람들에게는

시간이 꽤나 걸리는 작업일 것입니다

 

그래서 스타일링을 간편하게 도와주는 NativeBase 라이브러리가 있습니다

 

공식 홈페이지를 들어가면 더 상세한 정보를 알 수 있습니다

https://docs.nativebase.io

 

Getting Started | NativeBase | Universal Components for React and React Native

NativeBase 3.0 lets you build consistently across android, iOS & web. It is inspired by the Styled System and is accessible, highly themeable, and responsive.

docs.nativebase.io

 

한 가지를 같이 살펴보자면

 

위와 같이 여러 FORMS, DATE DISPAY, LAYOUT 등 여러 가지를 지원하고 있습니다

그중 FORMS의 INPUT을 보도록 하겠습니다

 

 

 

속성에 값을 할당하는 것만으로 손쉽게 스타일링을 할 수 있는 장점이 있습니다

시간 절약과 디자인이 조금 힘든 사람이라면 사용하는 것도 용이한 것 같습니다

 

 

 

 

 

 

그리고 아래와 같은 속성 값을 받아 여러 가지 기능도 같이 활용할 수 있습니다

 

 

 

 

그럼 직접 코딩을 한번 해보겠습니다

우선 아래와 같이 설치를 합니다

 

yarn add native-base@2 --save

 

NativeBase의 기능을 알아보자

 

 

앱의 상단 헤더 바 구현이 용이하다

아래와 같이 라이브러리의 컴포넌트를 사용하여 구성해 줍니다

 

import React, { Component } from 'react';
import { Container, Header, Content, Footer, Text } from 'native-base';
export default regiMember = () => {

    return (
      <Container>
        <Header />
        <Content padder>
          <Text>
          </Text>
        </Content>
        <Footer />
      </Container>
    );
 
}

 

 

상단 헤더 노출 이미지

 

위와 같이 헤드가 생성된 것을 확인할 수 있습니다

그러면 해더의 왼쪽, 오른쪽 <Left />, <Right />로

백키와 마이페이지 같은 활성 창을 노출시키는 기능을 구현할 수 있겠죠?

 

 

 

키보드 노출 및 태그에 필요한 액션 기능이 용이하다

 

input 같은 태그에 입력을 할 경우 키보드가 노출되는 기능도 <Content /> 태그로 구현한다면 

간편하게 구현할 수 있습니다

 

키자판 노출

 

 

레이아웃 구성이 직관적이다

 

가로세로 구분을 직관적으로 표현할 수 있습니다

Col, Row의 값으로 구분할 수 있으며, size의 속성으로 범위를 지정할 수 있습니다

 

import React, { Component } from 'react';
import { Container, Header } from 'native-base';
import { Col, Row, Grid } from 'react-native-easy-grid';
export default layout = () => {
    return (
      <Container>
        <Header />
        <Grid>
          <Col
            size={2}
            style={{ backgroundColor: '#635DB7', height: 200 }}
          ></Col>
          <Col
            size={1}
            style={{ backgroundColor: '#00CE9F', height: 200 }}
          ></Col>
        </Grid>
      </Container>
    );
}

 

 

아래와 같이 화면이 노출되고

지정된 영역도 직관적으로 확인이 가능합니다

 

레이아웃 화면

 

그 외에도 여러 가지 태그 속성들이 있습니다

잘 활용한다면 쉽게 스타일링할 수 있을 것 같습니다

 

태그 속성 목록

 

지금까지 nativeBase 라이브러리를 알아보았습니다

이것을 바탕으로 로그인 화면을 만들어 보려고 합니다

그럼 그때 다시 공부하도록 합시다!

 

언제나 그렇듯 코딩 공부는 힘이 들고 어렵네요

그래도 목표가 있으니!!

조금만 같이 힘내세요!!

 

아직 대모험은 끝나지 않았으니!!ㅋㅋ

파이팅!!

 

 

728x90
반응형
728x90
반응형

프로젝트를 진행하다 보면

지역별, 지점별 기준으로 업데이트하는 경우가 많습니다

그렇때마다 지점별, 지역별 쿼리를 만들어서 inset를 하는 경우가 있습니다

 

 

DEPT 테이블 행의 값을

EAST, WEST, MID의 세 테이블에 INSERT 하고 

테이블 구조는 DEPT와 같다고 가정합시다

 

 

 

한번에 여러 테이블 데이터 삽입

 

아래와 같은 구문을 사용하여 INSERT 하게되면

한번의 결과값으로 동시에 여러개의 테이블에 INSERT합니다

 

 

INSERT ALL
INTO EAST VALUES (DEPTNO, DNAME, LOC)
INTO WEST VALUES (DEPTNO, DNAME, LOC)
INTO MID VALUES (DEPTNO, DNAME, LOC)
SELECT (DEPTNO, DNAME, LOC) FROM DEPT WHERE DEPTNO = 20;

 

 

하지만 이 방법은 어떠한 조건없이

동일하게 같은 값들이 INSERT한다는 점으로

가용성이 떨어지는 면이 있습니다

 

 

한번에 여러 테이블 조건부 인설트 하기

 

다음 방법을 사용하면 같은 행의 값으로

둘 이상의 테이블에서 삽입할 수 있습니다

 

 

그럼 코드를 작성해봅시다

아래와 같이 코드를 작성하면

한 행으로 여러 테이블에 insert 할 수 있습니다

 

 

INSERT ALL
  WHEN LOC IN ('NEW YORK', 'BOSTON') THEN 
  	INTO EAST (DEPTNO, DNAME, LOC) VALUES (DEPTNO, DNAME, LOC)
  WHEN LOC = 'CHICAGO' THEN
    INTO MID (DEPTNO, DNAME, LOC) VALUES (DEPTNO, DNAME, LOC)
  ELSE
    INTO WEST (DEPTNO, DNAME, LOC) VALUES (DEPTNO, DNAME, LOC)
SELECT DEPT, DNAME, LOC
FROM DEPT

 

 

INSERT ALL과 INSERT FIRST 제대로 알고 사용하기

위와 같은 경우는 INSERT ALL 또는 INSERT FIRST 문을 사용할 수 있습니다

두 개의 구문은 같은 결과를 생성하지만

차이점은 존재합니다

 

INSERT FIRST는 조건이 참이 되는 즉시 WHEN-THEN-ELSE에서 빠져나오는

반면 INSERT ALL은 이전 테스트가 참으로 평가되더라도  

모든 조건을 평가합니다

 

따라서 INSERT ALL을 사용하여 같은 행을 둘 이상의 테이블에 삽입할 수 있습니다

그것이 싫다면 FIRST를 사용해야 합니다

 

mybatis를 사용하여 동적 쿼리와 같이 사용한다면

가용성은 더욱 높아질 거라 생각합니다

 

프로젝트를 진행하다보면 여러 데이터를 핸들링하게 되며

어떤 쿼리가 있는지 알아야지만

적재적소에 사용하여 시간을 절약하며

코드도 간결해질수 있을거라 생각합니다

 

오늘도 코딩으로 한걸음 나아갑시다

모두 화이팅하시고 힘내세요!!

아직 대모험은 끝나지 않았으니까요!!

 

화이팅!!

 

 

 

 

 

 

728x90
반응형
728x90
반응형

리얼 타임 데이터 베이스란?

플랫폼과 실시간 데이터를 송신할 수 있는 기능이라고 생각하시면 됩니다

그리고 기능을 사용하기 위해서는 파이어 베이스가 가지고 있는 고유한 기능들을 사용하면

쉽게 데이터를 주고받을 수 있습니다

 

이전에 포스팅을 했던 파일 저장소 스토리지는 이미지 파일을 정장하는 것이라면

리얼 타임 데이터베이스는 JSON 데이터를 받아

파이어 베이스의 데이터베이스에 저장하게 됩니다

 

두 가지의 기능의 차이점을 기억하시고

이제 리얼 데이터베이스를 생성하도록 하겠습니다

 

 

이전 포스팅에서 firebaseConfig.js 파일 생성한 것 기억하시나요?

 

 

2022.07.05 - [Server/Firebase] - React Native X Expo X 구글 파이어 베이스 서버 구축, 기본 세팅하기

 

React Native X Expo X 구글 파이어 베이스 서버 구축, 기본 셋팅하기

2022.06.30 - [Mobile/React Native] - [React Native X Expo] View, ScrollView, Text, Button, TouchableOpacity, Image 엘리먼트 & 태그 활용 리액트 네이티브 [React Native X Expo] View, ScrollView, Text,..

tantangerine.tistory.com

 

한번 확인해보시고 그럼 계속 진행하겠습니다

 

 

 firebaseConfig.js를 생성하셨으면

아래의 url 주소를 복사하셔서

firebaseConfig의 databaseURL에 value 값으로 지정해주시면 됩니다

 

리얼 타임 데이터 베이스 생성 #1

 

 

그럼 데이터 베이스에 데이터를 업로드를 한번 해보겠습니다.

이 방법은 파이어 베이스에서 직접 데이터를 업로드하는 방식입니다.

JSON 파일로 업로드가 가능하기 때문에

JSON 파일로 데이터를 만들어 놓았다면 쉽게 업로드는 하실 수 있을 겁니다.

 

오른쪽 상단 토글 아이콘을 선택하면 

JSON 데이터 불러오기라는 항목이 노출됩니다

 

 

리얼 타임 데이터 베이스 생성 #2

 

 

like라는 하위 경로에 데이터를 넣을지 아니면 최상위 경로에 넣을지도 정할 수 있습니다.

상위 경로로 이동하려면 아래의 파란색 블록으로 되어있는 url를 클릭하시면

이동이 가능합니다.

 

 

JSON 가져오기를 클릭하면 내 컴퓨터 내에서. JSON 파일을 업로드할 수 있는 창이 활성화됩니다.

 

 

 

리얼 타임 데이터 베이스 생성 #3

 

 

아래와 같이 창이 활성화되면 JSON 파일 업로드를 할 수 있습니다.

데이터 위치도 확인할 수 있어요!!

 

 

리얼 타임 데이터 베이스 생성 #4

 

 

저는 tip에 데이터를 넣었습니다.

그래서 아래와 같이 데이터가 구성이 되었네요

 

그럼 아래의 데이터를 읽어오는 방법을 구현해보겠습니다.

 

데이터 구조

 

 

Firebase 리얼 타임 데이터 베이스 Total Data Read. once() 함수 활용

 

ref()는 api통신을 할 수 있는 url 주소를 인자 값으로 받는다

그러면 통신이 이루어지고 특정 함수를 통해 데이터를 추가, 수정, 삭제를 할 수 있다

 

처음 databaseURL에 할당했던 url 주소가 기본 주소로 할당되어있어

전체 주소를 할당하지 않아도 됩니다

 

. then()은 자바스크립트의 api 통신 후 받은 데이터를 핸들링할 때 사용합니다.

 

아래의 함수는 파이어 베이스에서 데이터를 조회하기 위해

만들어 놓은 함수이기 때문에 그 규칙에 맞게 사용하면 되겠습니다.

공식문서에 맞게 사용하시면 됩니다.

 

snapshot이라는 변수명으로. val()를 사용하여 데이터를 리턴해올 수 있습니다.

그리고 그 데이터를 tip에 넣는 작업을 진행한 것입니다.

 

/tip이라는 경로에 있는 전체 데이터를 가져오게 되며

/tip/0이라는 경로에 있는 전체 데이터를 가져오게 된다는 의미는 위의 글과 같습니다

하지만 우리가 0에는 한 개의 데이터만 넣게 된다면

한개의 데이터만 읽어 올 수 있게 됩니다

 

그래서 데이터 구조의 요건을 어떻게 정립하는지가 더 중요할 수 있습니다

 

firebase_db.ref('/tip').once('value').then((snapshot) => {
   let tip = snapshot.val();
})

firebase_db.ref('/tip/0').once('value').then((snapshot) => {
   let tip = snapshot.val();
})

 

 

Firebase 리얼 타임 데이터 베이스 Save Data. set() 함수 활용

 

/like라는 곳에 데이터를 저장하려 합니다

저장할 때 사용하는 함수. set()입니다

 

내가 좋아하는 페이지를 저장하기 위해서는 누가, 무엇을 저장하는지에 대한 데이터가 필요합니다

유저의 유니크 아이디는 expo에서 제공하는 휴대폰 디바이스의 고유 키값을 사용합니다

그것을 활용하여 유저를 구분하는 인식 값으로 사용할 수 있습니다

 

유니크한 키값페이지의 시퀀스 넘버를 url경로로 지정하면 

아래와 같이 사용할 수 있습니다

 

expo install expo-application

import * as Application from 'expo-application';
const isIOS = Platform.OS === 'ios';


let uniqueId;
if(isIOS){
  let iosId = await Application.getIosIdForVendorAsync();
  uniqueId = iosId
}else{
  uniqueId = Application.androidId
}

firebase_db.ref('/like/'+userUniqueId+'/'+ tip.idx).set(tip,function(error){
    Alert.alert("찜 완료!")
});

 

 

 

파이어 베이스 플랫폼의 리얼 타임 데이터 베이스에 저장한 목록을 볼 수 있습니다

 

 

데이터 저장 현황

 

Firebase 리얼 타임 데이터 베이스 Delete Data. remove() 함수 활용

 

삭제할 데이터의 시퀀스 번호와 누구의 정보를 삭제할 것인지에 대한 유니크한 키값을 

url로 지정하여. remove() 함수를 통해 데이터를 삭제합니다.

 

삭제가 성공적으로 되었다면 

실시간으로 목록이 없어져야 합니다.

 

이때. ref(). once()함수를 사용하여 재조회를 해도 되지만

다시 조회한다면, 부하를 받을 수 있기 때문에 이렇게 처리하는 것이 좋을 수도 있습니다.

목록에 데이터 구조가 복잡하거나 부하가 되지 않는 상황이라면 구지 할 필요는 없을 것 같습니다.

 

아무튼 내부에서 자바 스크립터 filter를 활용하여 목록을 추출할 수 있습니다.

api를 호출하지 않고 목록에서 추가 삭제할 수 있다는 것만은 기억합시다.

 

const remove = async (cidx) => {
    let userUniqueId;
    
    if(isIOS){
        let iosId = await Application.getIosIdForVendorAsync();
          userUniqueId = iosId
    }else{
          userUniqueId = await Application.androidId
    }

    firebase_db
        .ref('/like/'+userUniqueId+'/'+cidx)
        .remove()
        .then(() => {
            Alert.alert("삭제 완료");
            let result = tip.filter((data,i)=>{
              return data.idx !== cidx
            })
            console.log(result)
            setTip(result)
    })
}

 

 

이것으로 파이어 베이스 세팅과 기능 구현을 끝이 났습니다.

파이어 베이스만 이러한 기능들을 구현하고 있고

다른 데이터 관리 툴들은 또 다른 기능들을 가지고 있습니다

여러 툴을 사용해야만 한다면 공부는 필수 겠지요!

 

오늘도 이렇게 포스팅을 마치며 한걸음 나아갑니다

 

언제나 그렇듯 힘들도 지치지만 힘내세요

아직 모험은 끝이 나지 않았으니까요!!

 

728x90
반응형
728x90
반응형

이전 포스팅에서 파이어 베이스와 앱 연동하는 방법을 

확인해보았습니다

 

못 보신 분들은 하단에 포스팅을 클릭해주세요

 

2022.07.05 - [Server/Firebase] - React Native X Expo X 구글 파이어 베이스 서버 구축, 기본 세팅하기

 

React Native X Expo X 구글 파이어 베이스 서버 구축, 기본 셋팅하기

2022.06.30 - [Mobile/React Native] - [React Native X Expo] View, ScrollView, Text, Button, TouchableOpacity, Image 엘리먼트 & 태그 활용 리액트 네이티브 [React Native X Expo] View, ScrollView, Text,..

tantangerine.tistory.com

 

 

그럼 본론으로 파이어 베이스의 몇 가지 기능을 설정하고 사용하는 방법까지 알아보겠습니다

알아보려는 기능은 2가지입니다

가장 기본적이면서 간단한 기능들이죠

 

  • 파일 스토리지 - 간단히 말하면 파일을 저장하는 장소라고 생각하시면 됩니다.
  • 리얼타임 데이터 베이스 - 파이어 베이스에서 제공하는 함수를 사용해서 데이터 저장, 수정, 삭제가 가능합니다 

 

 

정리하다 보니 리얼타임 데이터베이스는 다음 포스팅에서 해야겠네요

 

파일 스토리지 기능을 우선 알아보도록 하겠습니다

 

 

firebase의 파일 스토리지 설정 및 기능 구현 방법

 

 

파이어 베이스 홈페이지에서 

로그인 후 시작하기 버튼을 클릭하면

 

이전 포스팅까지 하셨다면 현재 프로젝트 공간에

자신의 프로젝트명이 노출되고 있는 것을 확인할 수 있습니다

클릭해서 이제 파일 스토리지를 활성화하로 가시죠!

 

파이어 베이스 파일스토리지 설정방법 #1

 

 

 

아래의 화면과 같이

Storage를 확인할 수 있으실 겁니다

그 버튼을 클릭하고

시작하기를 클릭하시면 이제 거의 끝난 거나 다름없습니다!

 

 

 

파이어 베이스 파일스토리지 설정방법 #2

 

아래와 같은 창이 노출되면 다음 버튼을 클릭하여 진행합니다

 

 

파이어 베이스 파일스토리지 설정방법 #3

 

 

그리고 파일 스토리지와 저장 장소를 설정합니다

지금 살고 있는 지역과 비슷하면 괜찮겠죠?

그래서 선택하고 완료 버튼을 클릭합니다

 

 

파이어 베이스 파일스토리지 설정방법 #4

 

파일을 저장할 수 있는 스토리지의 화면이 활성화됩니다

그럼 이미지만 저장해서 관리할 수 있는 폴더를 생성하면 편하겠죠?

폴더 모양의 아이콘을 클릭해서 폴더를 만들어 줍니다

 

저는 폴더명을 images라고 하려고요

빨간색으로 블록이 처리된 부분은 파일 저장 경로가 노출되어있는 것을 확인할 수 있습니다

 

파이어 베이스 파일스토리지 설정방법 #5

 

 

폴더를 생성하면 경로가 변경된 것을 확인할 수 있으며,

파일 업로드 버튼을 클릭하여 파일도 저장된 모습을 확인할 수 있습니다

 

 

파이어 베이스 파일스토리지 설정방법 #6

 

 

이렇게 저장된 파일은 외부 경로를 통해 이미지를 불러올 수 있어요

이미지 불러오는 법은 

마지막에 링크를 걸어 두겠습니다

 

 

 

 

이렇게 파일을 저장하는 공간을 만들어보았습니다

다음 포스팅에서는 리얼타임 데이터베이스 기능으로

저장공간에 파일을 저장하는 방법과

데이터를 추가, 삭제, 수정하는 방법을 알아보도록 하겠습니다

 

1일 1포스팅을 하려고 노력하고 있는데 쉽지는 않네요

그래도 이렇게 포스팅을 하며 복습하니 기억에도 많이 남고 하네요

힘들겠지만 오늘도 한걸음 나아갑시다!!

 

힘내시고 아직 대모험은 끝나지 않았으니까요!!

파이팅!!

 

 

 

 

2022.06.30 - [Mobile/React Native] - [React Native X Expo] View, ScrollView, Text, Button, TouchableOpacity, Image 엘리먼트 & 태그 활용 리액트 네이티브

 

[React Native X Expo] View, ScrollView, Text, Button, TouchableOpacity, Image 엘리먼트 & 태그 활용 리액트 네이티

View, ScrollView, Text, Button, Image 엘리먼트 & 태그 활용 엘리먼트 활용 화면의 영역(레이아웃)을 잡아주는 엘리먼트이다. App.js 상에서 View는 화면 전체 영역을 가진다. 아래와 같이 화면을 분할.

tantangerine.tistory.com

 

728x90
반응형
728x90
반응형

2022.06.30 - [Mobile/React Native] - [React Native X Expo] View, ScrollView, Text, Button, TouchableOpacity, Image 엘리먼트 & 태그 활용 리액트 네이티브

 

[React Native X Expo] View, ScrollView, Text, Button, TouchableOpacity, Image 엘리먼트 & 태그 활용 리액트 네이티

View, ScrollView, Text, Button, Image 엘리먼트 & 태그 활용 엘리먼트 활용 화면의 영역(레이아웃)을 잡아주는 엘리먼트이다. App.js 상에서 View는 화면 전체 영역을 가진다. 아래와 같이 화면을 분할.

tantangerine.tistory.com

 

위에는 리액트 네이티비의 화면 구성하는 포스팅입니다

관심있으시면 확인 해보세요~~!

 

파이어 베이스란?

 

파이어 베이스는 서버에 대한 지식이 많이 없어도

간편하게 서버를 구축할 수 있게 해주는 서비스입니다

이러한 것들을 서버리스라고 합니다

 

여기서 간략하게 서버리스가 무엇인지 설명하자면,

개발자가 서버를 관리할 필요 없이 애플리케이션을 빌드하고 실행할 수 있도록 하는

클라우드 네이티브 개발 모델입니다

 

장점은 애플리케이션이 필요할 경우에만 시작되며,

코드 실행이 종료되면 비용도 청구 되지않아 비용과 효율성이라는 장점이 있습니다

그 외에도 애플리케이션 스케일링 및 서버 프로비저닝과 같은

일상적이고 사소한 작업들로 부터 개발자의 부담을 덜수 있습니다

서버리스 파이어베이스

 

파이어 베이스 같은 경우는 복잡한 비즈니스 업무를 수행하기 힘들며,

서비스 비용도 규모가 커질 수록 지출비용은 늘어나게됩니다

다른 서버구축보다도 말이지요

 

 

하지만 소규모 프로젝트라면 부족함이 없다고 생각합니다

그럼 프로젝트를 생성해서 서버를 구축해볼까요??

 

구글 계정만있다면 

구글에서 파이어 베이스라고 검색해 쉽게

프로젝트를 만들어 서버를 구축할 수 있습니다

 

검색을 하면 

아래와 같이 홈페이지를 확인할 수 있습니다

 

 


파이어 베이스 프로젝트 생성하기

 

구글 파이어 베이스 프로젝트 생성 #1

 

 

시작하기를 클릭하시고 다음 화면으로 넘어갑시다!

 

 

구글 파이어 베이스 프로젝트 생성 #2

 

버튼을 클릭하고 다음 화면으로 갑시다

프로젝트 이름을 설정할 수 있을거예요!

 

구글 파이어 베이스 프로젝트 생성 #3

 

버튼을 클릭하고  다음으로 넘어가면 프로젝트에 대한 

Google 애널리틱스를 연동해서 관리할수 있는 선택창을 볼 수 있습니다

 

 

구글 파이어 베이스 프로젝트 생성 #4

 

다음 화면은 애널리틱스의 위치를 기입하면 프로젝트를 만들 수 있게됩니다

 

구글 파이어 베이스 프로젝트 생성 #5

 

그리고 다음은 시간이 몇분 지나면,

서버 프로젝트 관리 페이지로 이동하게됩니다

 

구글 파이어 베이스 프로젝트 생성 완료!

 


 

 

파이어 베이스를 앱에 연동하기

 

파이어 베이스를 연동하기 위해서는 IOS인지 안드로이드로 개발하는지에 따라

조금 다름니다

 

지금 리액트 네이티브 X 엑스포로 개발하는 중이기때문에

웹 SDK를 이용하면 쉽게 파이어 베이스 서버 구축이 가능합니다

 

 

파이어 베이스를 와 연동하기 #1

 

코드를 클릭하고 다음화면으로 가면

앱 닉네임을 기입하고

호스팅은 난중에 설정할 수 있으니 

지금은 넘어가도록 하겟습니다

 

파이어 베이스와 앱 연동하기 #2

 

앱을 등록하게 되면

우리가 사용할 코드 정보가 있습니다

그 정보를 우리 프로젝트에 js파일로 생성하여

코드를 삽입을 하여 연동에 필요한 정보를 사용해 봅시다!

 

파이어 베이스와 앱 연동하기 #3

 


 

파이어 베이스를 앱에 도구 설치 및 연동

 

Expo에서 파이어베이스를 사용할 수 있게

Expo의 firebase를 설치를 합니다

 

expo install firebase

 

 

파일 위치는 최상단에 생성하고 오른쪽과 같이 코드를 기입하면된다

파이어 베이스 연동관련 중요 키가 되는 부분은 플렛폼에서 복사해서 붙여넣기를 한다

 

 

파이어 베이와 앱 연동하기 #4

 

 

이때 중요한것은 databaseUrl이 설정이 안되어있습니다

그러므로 파이어 베이스 플렛폼의 리얼 타임 데이터 베이스에 들어가셔서

복사를 한다음 firebaseConfig안에 값을 지정해주시길 바랍니다

 

파이어 베이와 앱 연동하기 #5

 

 

 

이제 파이어 베이스와 앱 연동은 기본적인 설정은 끝이 났습니다

먼가 엄청 길게 적었지만 이미지가 거의 반이니 너무 길다고 포기하지마시고

끝까지 화이팅해요!

 

아직 모험은 끝나지 않았으니까요!

 

 

 

 

728x90
반응형
728x90
반응형

 

이전 포스팅이였던  스택 네비게이션도 한번 확인 해보세요~

 

2022.07.04 - [Mobile/React Native] - React Native_스택 네비게이션 활용 페이지와 컴포넌트 이동

 

React Native_스택 네비게이션 활용 페이지와 컴포넌트 이동

스택 네비게이션이란? 컴포넌트에서 컴포넌트로 이동을 용이하게 해주는 기능이다. 즉 페이지를 이동하는 방법이라고 생각하면된다. 컴포넌트를 이동이라고는 하지만 솔직히 페이지 이동이라

tantangerine.tistory.com

 

 

앱 공유하기 기능 - Share

 

유튜브나 블로그 글 같은 것을 보다 보면 공유하기 버튼을 클릭해서

앱들 간의 다른 사람들과 공유하는 기능을 보실 수 있었을 것입니다.

 

react-nativeShare함수를 사용하면 간편하게 기능을 구현할 수 있습니다

 

 

import { Share } from "react-native"

 

위와 같이 import를 해서 사용합니다

 

Share.share({ message: '내용' });

 

 

share 함수를 사용하면 우리가 흔히 볼 수 있는 공유 창이 나타나고 내용들이 메세지로 전달됩니다.

 

 

import React from 'react';
import { TouchableOpacity,Share } from 'react-native';


export default function DetailPage({navigation,route}) {	
    const share = () => {
        Share.share({
            message:`${tip.title} \n\n ${tip.desc} \n\n ${tip.image}`,
        });
    }
    
    return (
      <TouchableOpacity style={styles.button} onPress={()=>share()}>
        <Text style={styles.buttonText}>
          공유하기
        </Text>
      </TouchableOpacity>
    )
}

 

TouchableOpactiy 컴포넌트에 onPress속성에 share함수만 넣어서 실행하면됩니다.

 그때 실행할 때 인자값으로 공유할 내용을 같이 전달하면 기능 구현은 끝입니다.

 

 

아래와 같이 공유 기능이 노출됩니다

 

공유하기 버튼클릭시 이미지

 

반응형

 

 

공유 전달된 이미지

 

이미지도 지금은 글자로 들어가지만 

<img> 태그를 사용하면 문자로 보낼 경우 이미지를 노출시킬수도 있습니다

 

 


 

앱 외부링크 이동 기능 - Linking 

 

앱에서 외부링크를 여는 방법은 Expo에 제공해주는 라이브러리를 설치하여 

LinkingopenURL 함수를 사용하여 기능 구현을 합니다

 

import React from 'react';
import { TouchableOpacity,Share } from 'react-native';


export default function DetailPage({navigation,route}) {	
    const link = () => {
        Linking.openURL("https://spartacodingclub.kr")
    }
    
    return (
       <TouchableOpacity style={styles.button} onPress={()=>link()}>
         <Text style={styles.buttonText}>
           외부 링크
         </Text>
       </TouchableOpacity>
    )
}

 

정말 위의 코드만 보면 정말 간단하죠?

 

코드를 작성하면서 저 또한  앱에 대한 기능 공부를 복습하게되었습니다

저도 저만의 앱을 만들려고 앱을 공부하고 있습니다

 

아직까지 모험은 끝나지 않았으니까요!!

오늘도 한 발자국 나아갑시다!!

화이팅!!

 

728x90
반응형
728x90
반응형

스택 네비게이션이란?

컴포넌트에서 컴포넌트로 이동을 용이하게 해주는 기능이다.

즉 페이지를 이동하는 방법이라고 생각하면된다.

 

페이지이동에 대한 과정이다

 

컴포넌트를 이동이라고는 하지만 솔직히 페이지 이동이라고 하는것이 맞는 것 같아요.

하지만 컴포넌트 이동이라고 표현하는 것도 코드 구조를 보면 약간은 이해가 갈거예요.

 

왜 그렇냐면 화면에 노출 시킬 페이지를 import하여 Stack.Screen 속성 component에 할당합니다.

모든 페이지를 그렇게 연결하게되면 페이지이동을 간편하게 할 수 있습니다

 

아래의 코드를 보고 다시 한번 더 확인해보아요.

 

 

스택네비게이션의 활용방법

 

라이브러리 설치

yarn add @react-navigation/stack

 

 

/navigation/StackNavigator.js

폴더를 생성하고 파일을 만들어 코드 작성을 합니다.

 

StackNavigator.js

import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';

import DetailPage from '../pages/DetailPage';
import MainPage from '../pages/MainPage';

const Stack = createStackNavigator();

const StackNavigator = () =>{
    return (
         <Stack.Navigator
            screenOptions={{
                headerStyle: {
                    backgroundColor: "white",
                    borderBottomColor: "white",
                    shadowColor: "white",
                    height:100
                },
                headerTitleAlign:'left',
                headerTintColor: "#000",
                headerBackTitleVisible: false
            }}
            
        >
            <Stack.Screen name="MainPage" component={MainPage}/>
            <Stack.Screen name="DetailPage" component={DetailPage}/>
        </Stack.Navigator>
    )
}

export default StackNavigator;

 

 

createStackNavigator() 함수를 변수에 할당하여 변수로 활용합니다.

 

Stack에 저장된 스택 네비게이션에는 몇가지 태그가 존재한다. 그 중에는 Navigator, Screen있습니다.

 

 

Stack.Navigator

Stack.Navigator는 페이지에 헤더가 되는 부분을 스타일링을 해주는 컴포넌트있습니다.

이 컴포넌트에서는 페이지에서 헤더가 별도로 존재하지않아도 공통으로 관리할 수 있습니다.

배경 색깔, 버튼 색깔, 페이지 타이틀, 타이틀 위치 등등

 

 

Stack.Screen

Stack.Screen은 활용하면 페이지를 할당해서 스택 네비게이션 함수를 사용하여

스택 네비게이션에 관리가 용이하다. 그리고 Stack.Screen에 등록됩니다.

모든 페이지들은 navigationrouter 객체를 넘겨받아 사용할 수 있습니다.

 

navigation.setOptions({ title: '메인 페이지' })

- 해당 페이지의 제목을 설정할 수 있습니다.

 

navigation.navigate("DetailPage")

- Stack.screen에서 등록된 속성 name으로 지정하면 페이지로 이동하는 함수입니다.

 

navigation.navigate("DetailPage", { title: '페이지' })

- 페이지를 이동하면서 두번째 인자값의 객체를 이동된 페이지에서 router로 받을 수 있습니다.

 

 

이러한 기능들이 다 사용하여 페이지를 이동시 데이터를 주고 받을 수 있습니다.

그럼 메인 페이지의 코드와 상세 페이지의 코드를 확인해서 어떻게 사용하는지 확인해 보아요!! 

 

 

MainPage.js

import React,{useState,useEffect} from 'react';
import { StyleSheet, Text, View, Image, TouchableOpacity, ScrollView} from 'react-native';

const main = 'https://storage.googleapis.com/sparta-image.appspot.com/lecture/main.png'
import data from '../data.json';
import Card from '../components/Card';
import Loading from '../components/Loading';
import { StatusBar } from 'expo-status-bar';
export default function MainPage({navigation,route}) {
  const [state,setState] = useState([])
  const [cateState,setCateState] = useState([])
  const [ready,setReady] = useState(true)

  useEffect(()=>{
    setTimeout(()=>{
        navigation.setOptions({
          title:'메인 페이지'
        })  
        setState(data.tip)
        setCateState(data.tip)
        setReady(false)
    },1000)
 
    
  },[])

  const category = (cate) => {
    if(cate == "전체보기"){
        setCateState(state)
    }else{
        setCateState(state.filter((d)=>{
            return d.category == cate
        }))
    }
}

  let todayWeather = 10 + 17;
  let todayCondition = "흐림"

  return ready 
    ? <Loading/> 
    :  (
        <ScrollView style={styles.container}>
          <StatusBar style="light" />
          <Image style={styles.mainImage} source={{uri:main}}/>
          <View style={styles.cardContainer}>
             {
              cateState.map((content,i)=>{
                return (<Card content={content} key={i} navigation={navigation}/>)
              })
            }
          </View>
        </ScrollView>
       )
}

 

navigation.setOptions({ title:'메인 페이지' })  

 

navigation.setOptions를 사용하여 현재 페이지의 타이틀, 배경색깔등을 변경할 수 있습니다

 

 

반응형

 

<Card navigation={navigation}  />

 

위와 같이 컴포넌트에 navigation을 전달하게되면

해당 컴포넌트 내부에서 navigation을 사용하여 detailPage 화면으로 이동할 수 있습니다.

 

 

Card.js

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

export default function Card({content,navigation}){
    return(
        <TouchableOpacity style={styles.card} onPress={()=>{navigation.navigate('DetailPage',content)}}>
            <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>
        </TouchableOpacity>
    )
}

 

navigation.navigate('DetailPagae', content)

 

인자 값으로 받은 content와, navigation 두개를 활용하여

<TouchableOpacity /> 컴포넌트에서 onPress 속성에 스택네비게이션 함수를 사용하는 모습을 볼 수 있습니다

 

 

그래서 MainPage에서 Card 리스트가 노출되어 클릭을 하는 순간

Card의 이벤트로 DetailPage로 화면이동이 됩니다

 

 

DetailPage.js

import React,{useState,useEffect} from 'react';
import { StyleSheet, Text, View, Image, ScrollView,TouchableOpacity,Alert } from 'react-native';

export default function DetailPage({navigation,route}) {
    const [tip, setTip] = useState({
        "idx":9,
        "category":"재테크",
        "title":"렌탈 서비스 금액 비교해보기",
        "image": "https://storage.googleapis.com/sparta-image.appspot.com/lecture/money1.png",
        "desc":"요즘은 정수기, 공기 청정기, 자동차나 장난감 등 다양한 대여서비스가 활발합니다. 사는 것보다 경제적이라고 생각해 렌탈 서비스를 이용하는 분들이 늘어나고 있는데요. 다만, 이런 렌탈 서비스 이용이 하나둘 늘어나다 보면 그 금액은 겉잡을 수 없이 불어나게 됩니다. 특히, 렌탈 서비스는 빌려주는 물건의 관리비용까지 포함된 것이기에 생각만큼 저렴하지 않습니다. 직접 관리하며 사용할 수 있는 물건이 있는지 살펴보고, 렌탈 서비스 항목에서 제외해보세요. 렌탈 비용과 구매 비용, 관리 비용을 여러모로 비교해보고 고민해보는 것이 좋습니다. ",
        "date":"2020.09.09"
    })
    
    useEffect(()=>{
        console.log(route)
        navigation.setOptions({
            title:route.params.title,
            headerStyle: {
                backgroundColor: '#000',
                shadowColor: "#000",
            },
            headerTintColor: "#fff",
        })
        setTip(route.params)
    },[])

    const popup = () => {
        Alert.alert("팝업!!")
    }
    return ( 
        <ScrollView style={styles.container}>
            <Image style={styles.image} source={{uri:tip.image}}/>
            <View style={styles.textContainer}>
                <Text style={styles.title}>{tip.title}</Text>
                <Text style={styles.desc}>{tip.desc}</Text>
                <TouchableOpacity style={styles.button} onPress={()=>popup()}><Text style={styles.buttonText}>팁 찜하기</Text></TouchableOpacity>
            </View>
        </ScrollView>
    
    )
}

 

Card 컴포넌트에서 두번째 인자값으로 content를 전달했었죠?

 

navigation.navigator 함수로 전달 할 경우

Stack.Screen으로 component를 연결해야지만 router로 받을수 있습니다

 

router.params 안에 객체의 값이 들어 있으니 참고하세요!

 

 

 

지금까지 스택네비게이션을 알아보았습니다.

복잡하지만 차근 차근 구조를 익히다보면 쉽게 하실수 있을거예요

 

마지막으로 간략히 설명하자면,

 

처음 스택네비게이션을 설치 후

파일을 만든다음 Stack.Navigator의 부모태그와 Stack.Screen의 자식태그로 지정하여

코드를 작성해주고 원하는 페이지를 속성으로 묶어 주기만하면 끝이라는 점!

 

그리고

부모태그 자식태그의 파일을 import 해서 사용하기만 하면

된다는 점을 인지하여 주시길바랍니다

 

 

이렇게 오늘도 저도 복습하며 블로그를 이어나가네요

요즘 다시 블로그를 살려볼려고 힘을 내고 있습니다

 

모두들 대모험은 아직 끝나지 않았습니다

화이팅 하시고 

 

다음 포스팅에서 뵐게요~

 

 

이전 포스팅은 밑에서~

2022.06.30 - [모바일/React Native] - [React Native X Expo] View, ScrollView, Text, Button, TouchableOpacity, Image 엘리먼트 & 태그 활용 리액트 네이티브

 

[React Native X Expo] View, ScrollView, Text, Button, TouchableOpacity, Image 엘리먼트 & 태그 활용 리액트 네이티

View, ScrollView, Text, Button, Image 엘리먼트 & 태그 활용 엘리먼트 활용 화면의 영역(레이아웃)을 잡아주는 엘리먼트이다. App.js 상에서 View는 화면 전체 영역을 가진다. 아래와 같이 화면을 분할.

tantangerine.tistory.com

 

728x90
반응형
728x90
반응형

엘리먼트 & 태그에 Style 입히기

 

이전 포스팅에서 만들어보았던 화면들로 스타일을 입혀보자

이전 포스팅을 보고 싶다면 아래를 클릭!!

 

2022.06.30 - [모바일/React Native] - [React Native X Expo] View, ScrollView, Text, Button, TouchableOpacity, Image 엘리먼트 & 태그 활용 리액트 네이티브

 

[React Native X Expo] View, ScrollView, Text, Button, TouchableOpacity, Image 엘리먼트 & 태그 활용 리액트 네이티

View, ScrollView, Text, Button, Image 엘리먼트 & 태그 활용 엘리먼트 활용 화면의 영역(레이아웃)을 잡아주는 엘리먼트이다. App.js 상에서 View는 화면 전체 영역을 가진다. 아래와 같이 화면을 분할.

tantangerine.tistory.com

 

React Native에서 사용하는 styleSheet 활용 문법

 

태그에 스타일을 입히는 방법은 몇 가지가 존재합니다

 

  • 모든 태그에는 공통적인 style 속성이 존재한다 그래서 그 속성에 값을 직접 주는 방법
  • 리액트 네이티브에서 제공하는 StyleSheet 모듈을 임 폴트 해서 사용하는 방법
    • StyleSheet는 모듈로 create 함수를 사용하여 객체로 만들어서 스타일을 정리해두어 사용하게 될 경우 객체로 이름을 부여하여 사용이 가능합니다
import { StyleSheet } from 'react-navite'

const styles = StyleSheet.create({
	container: {
    		backgroundColor: '#77'
    }
})

위와 코드를 작성하게 되면 style속성에 객체로 값을 부여할 수 있게 됩니다

 

<View style={styles.container}>

 

style속성에 우리가 만들어 두었던 styles의 객체로 container를 불러서 사용할 수 있습니다

 


 

자주 사용하는 스타일 속성

 

지금까지는 스타일을 입히는 방법을 알아보았다면

이제는 어떠한 속성들이 있는지를 알아보시죠!

하지만 그 많은 것들을 다 알 필요는 없습니다

 

왜냐하면 모든 사람들이 그것을 다 외우지는 않으니까요

 

그때그때 상황에 맞게 필요할 때마다 속성을 검색해서

사용하는 방법을 익히면 됩니다

그렇다고 막 익히려고 하지 않아도 자연스럽게 채득 할 수 있을 겁니다  

 

import { StyleSheet } from 'react-native';

const styles = StyleSheet.create({
  container: {
    //영역을 잡는 속성입니다. 따로 자세히 다룹니다.
    //flex: 1은 전체 화면을 가져간다는 뜻입니다
    flex: 1,
    //영역의 배경 색을 결정합니다
    backgroundColor: '#fff',
    //아래 두 속성은 영역 안의 컨텐츠들의 배치를 결정합니다. 
    //flex를 자세히 다룰때 같이 자세히 다룹니다
    justifyContent:"center",
    alignContent:"center"
  },
  textContainer: {
    //영역의 바깥 공간 이격을 뜻합니다(하단 이미지 참조)
    margin:10,
    //영역 안의 컨텐츠 이격 공간을 뜻합니다(하단 이미지 참조)
    padding: 10,
    //테두리의 구부러짐을 결정합니다. 지금 보면 조금 둥글죠?
    borderRadius:10,
    //테두리의 두께를 결정합니다
    borderWidth:2,
    //테두리 색을 결정합니다
    borderColor:"#000",
    //테구리 스타일을 결정합니다. 실선은 solid 입니다
    borderStyle:"dotted",

  },
  textStyle: {
    //글자 색을 결정합니다. rgb, 값 이름, 색상코드 모두 가능합니다
    color:"red",
    //글자의 크기를 결정합니다
    fontSize:20,
    //글자의 두께를 결정합니다
    fontWeight:"700",
    //가로기준으로 글자의 위치를 결정합니다
    textAlign:"center"
  }
});

위와 같이 정말 여러 속성들이 있죠?

저도 매일 찾아서 하니깐 너무 신경 쓰지 말고 이런 것이 있구나 하고 다음으로 넘어갑시다!!

 


 

style 속성 중 중요한 Flex 제대로 알기

  • flex
    • 화면을 구성할 경우 정말 중요한 것이 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>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex:1
  },
  containerOne: {
    flex:1,
    backgroundColor:"red"
  },
  containerTwo:{
    flex:2,
    backgroundColor:"yellow"
  }
});

 

위와 같이 flex에 숫자를 넣어서 값을 할당할 수 있습니다

그렇게 되면 전체 화면에 대한 비율을 나타나게 됩니다

위에는 flex를 3번을 사용했습니다

하지만 태그 구조상 상위 View태그 하나에 하위 View 태그 2개가 존재합니다

그렇기 때문에 상위 태그의 flex 1은 전체를 나타내는 비율이며

그 안에 하위 2개의 하위 태그가 다시 비율을 지정하게 됩니다

2개의 하위 태그는 각각 1과 2를 flex에 부여하고 있어 

1 + 2를 하여 1/3과 2/3의 비율로 화면이 구성되게 됩니다

 

위의 코드를 구성화면이며 1/3과 2/3의 비율로 화면이 분활되어있음을 확인할 수 있다

 

그럼 한 가지 예를 더 보고 넘어가도록 합시다

 

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}>

        </View>

      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex:1
  },
  containerOne: {
    flex:1,
    backgroundColor:"red"
  },
  containerTwo:{
    flex:2,
    backgroundColor:"yellow"
  },
  innerOne: {
    flex:1,
    backgroundColor:"blue"
  },
  innerTwo: {
    flex:4,
    backgroundColor:"orange"
  }
});

 

이 경우는 1개의 상위 view태그에 2개의 하위 태그

그리고 한 개의 하위 태그는 다시 2개로 분할 되어있죠

이 경우는 처음 2개의 하위 태그 flex 1과 2로 분할하여

2/3에 해당하는 영역에서 다시 두개로 나눈값을 1/5, 4/5분할하게 됩니다 

그래서 flex 값이 같더라도 영역의 크기가 달라지게 됩니다

 

위의 코드를 구현한 화면이다

 

 

반응형

  • FlexDirection
    • 자식태그의 영역을 정렬방향을 세로 또는 가로로 지정할 수 있는 속성
    • flexDirection: "row" 가로 방향,  flexDirection: "column" 세로 방향
    • 기본값은 colunm입니다
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}>
        </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,
    backgroundColor:"orange"
  }
});

 

 

정렬이 빨강 영역보다 다르다는 것을 알 수 있다

 


 

  • justifyContent
    • justifyContent는 상위 태그에서 지정된 flexDirection의 방향과 어떻게 정렬할것인지 지정하는 속성입니다.
    • flexDirection을 꼭 지정해야 justifyContent를 지정할 수 있는것을 기억하세요
    • 속성에는 flex-start, center, flex-end, space-between, space-around이 있습니다.
    • flex-start는 영역들이 제일 상단에서 부터 정렬됩니다.
    • center는 영역들이 중앙에 모여있는 형태가 된다.
    • flex-end는 제일 하단에서 부터 정렬된다 
    • space-between는 여러 영역들을 처음 중간 끝에 나열하게된다.
    • space-around는 여러 영역들을 처음 중간 끝을 일정한 간격으로 나열하게된다

어떻게 정렬되는지 확인이 가능하다

 

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,
    justifyContent:"flex-start",
    backgroundColor:"orange"
  }
});

 

 

왼쪽에 치우쳐진 것을 볼수 잇다

 

부모 태그 영역을 flexDirection이 무엇으로 지정했는지가 중요합니다

 

 


 

  • alignItem
    • alignItem은 flexDirection의 반대로 정렬됩니다
    • flexDirection 값이 coloumn으로 지정 되었다면, 자식 태그에 alignItem의 값을 지정하게 되면 좌우로 정렬 됩니다
    • row으로 지정되었다면, 반대가 된다
    • flex-start, center, flex-end, stretch 속성을 가지고 있습니다

 

이미지를 잘 확인하면서 속성들이 어떻게 표현하는지 확인 합시다

 

 

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}>
          <View style={styles.content}></View>
        </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,
    backgroundColor:"orange",
    alignItems:"flex-end"
  },
  content: {
    width:50,
    height:50,
    backgroundColor:"#000"
  }
});

 

 

이미지를 확인해보세요!!

 

 

2개의 포스팅으로 앱 화면 만들어 보았습니다

저도 개발자가 되고 공부를 많이 하고있습니다

이 직업은 항상 공부를 해야 한다는 것이 부담되고 힘들기도 합니다

하지만 공부라고 생각하지마시고 사이드프로젝트를 하면서

자기만의 사이트를 만들어보고, 다른 기능들도 붙여보고,

회사에서 사용한 코드들을 나만의 노트에 정리도 하면서,

흥미를 붙이는 과정이 정말 중요한것 같습니다

그럼 모두 화이팅 하시고!!

 

즐거운 코딩시간이 되었으면 합니다

화이팅!!

 

 

728x90
반응형
728x90
반응형

View, ScrollView, Text, Button, Image 엘리먼트 & 태그 활용 

<View> 엘리먼트 활용

  • 화면의 영역(레이아웃)을 잡아주는 엘리먼트이다.
  • App.js 상에서 View는 화면 전체 영역을 가진다.
  • 아래와 같이 화면을 분할할 수 있다.
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}>
      <View style={styles.subContainerOne}></View>
      <View style={styles.subContainerTwo}></View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  subContainerOne: {
    flex:1,
    backgroundColor:"yellow"
  },
  subContainerTwo: {
    flex:1,
    backgroundColor:"green"
  }
});
  • 각 태그들에는 style이라는 속성을 가지고 있다
  • 속성은 하단에 스타일 코드 객체의 키값을 할당하여 엘리먼트에 스타일을 부여한다

 

View호 화면을 분할하고 영역을 나누려면

스타일 문법(StyleSheet)과 같이 사용해야 한다

 

스타일 문법(StyleSheet)은 다음 포스팅에서 확인하고

View는 화면의 영역을 잡는 엘리먼트라는 것만 알아두자

 

 

아래의 이미지는 위의 코드로 표현한 앱 화면이다 

상위 View엘리먼트 안에 하위 2개의 View 엘리먼트로 인해 2개의 영역이 표현된다.

코드로 표현한 앱화면이다

 


 

<ScrollView> 엘리먼트 활용

  • 앱 화면에 노출되는 영역보다 엘리먼트가 벗어나면 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>
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  textContainer: {
    height:100,
    borderColor:'#000',
    borderWidth:1,
    borderRadius:10,
    margin:10,
  },
  textStyle: {
    textAlign:"center"
  }
});

 

상위 엘리먼트를  View로 구현했다면 마지막 부분이 짤려서 보이질 않는다.

ScrollView를 사용하면 스크롤이 가능해지면서 마지막부분도 보이게된다.

 

위의 코드로 표현된 앱 화면

 


반응형

<Text> 엘리먼트 활용

  • 앱에 글을 표현하려면 꼭 사용해야 할 엘리먼트이다.
  • 방금 전 위에서 배운 ScrollView 엘리먼트 안에 문자를 작성하면 오류가 발생한다.
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text>문자는 Text 태그 사이에 작성!!</Text>
      <Text>문자는 Text 태그 사이에 작성!!</Text>
      <Text>문자는 Text 태그 사이에 작성!!</Text>
      <Text>문자는 Text 태그 사이에 작성!!</Text>
      <Text>문자는 Text 태그 사이에 작성!!</Text>
      <Text>문자는 Text 태그 사이에 작성!!</Text>
      <Text>문자는 Text 태그 사이에 작성!!</Text>
      <Text>문자는 Text 태그 사이에 작성!!</Text>
      <Text>문자는 Text 태그 사이에 작성!!</Text>
      <Text>문자는 Text 태그 사이에 작성!!</Text>
      <Text>문자는 Text 태그 사이에 작성!!</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

 


 

<Button> 엘리먼트 활용

  • Button 태그를 이용해서 손쉽게 버튼을 만들 수 있다
  • Button 태그에는 title, color, onPress 등의 속성을 가지고 있는데, 속성을 잘 활용하면 여러기능을 구현할 수 있다.
import React from 'react';
import { StyleSheet, Text, View, Button, Alert } from 'react-native';

export default function App() {
  const customAlert = () => {
    Alert.alert("JSX 밖에서 함수 구현 가능!")
  }
  return (
    <View style={styles.container}>
      <View style={styles.textContainer}>
        <Text style={styles.textStyle}>아래 버튼을 눌러주세요</Text>
        <Button 
          style={styles.buttonStyle} 
          title="버튼입니다 "
          color="#f194ff" 
          onPress={customAlert}
        />
        <Button 
            style={styles.buttonStyle} 
            title="버튼입니다 "
            color="#FF0000" 
            onPress={() => {customAlert()}}
          />
          </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  textContainer: {
    height:100,
    margin:10,
  },
  textStyle: {
    textAlign:"center"
  },
});

 

위의 코드는 Button 태그에 onPress 속성을 부여하여 앱화면 버튼영역 터치시 얼럿창을 노출하는 기능을 구현한 것이다

함수는 ES6문법인 화살표 함수를 사용해도 된다.

하지만 Button 태그는 자신의 영역을 갖기때문에 스타일을 부여하기가 어려움이 있다.

아래의 코드 처럼 ScrollView에서 카드 형식으로 만든 앱 화면이면 Button 태그를 사용하기 어렵다 그러므로 <TouchableOpacity> 태그를 활용하면 화면에 영향을 주지않고 쉽게 구현할 수 있다.

 


 

<TouchableOpacity> 태그를 활용해서 Button 태그 대체하기 

  • <ScrollView> 상위 태그로 하위태그는 View를 사용하지만 그것을 TouchableOpacity태그로 대체하면 임의의 영역과 디자인에 버튼 기능을 구현하고 싶을경우 주로 사용한다
import React from 'react';
import { StyleSheet, Text, View, ScrollView, TouchableOpacity, Alert } from 'react-native';

export default function App() {
  const customAlert = () => {
    Alert.alert("TouchableOpacity에도 onPress 속성이 있습니다")
  }
  return (
    <ScrollView style={styles.container}>
      <TouchableOpacity style={styles.textContainer} onPress={customAlert}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </TouchableOpacity>
      <TouchableOpacity style={styles.textContainer} onPress={customAlert}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </TouchableOpacity>
      <TouchableOpacity style={styles.textContainer} onPress={customAlert}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </TouchableOpacity>
      <TouchableOpacity style={styles.textContainer} onPress={customAlert}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </TouchableOpacity>
      <TouchableOpacity style={styles.textContainer} onPress={customAlert}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </TouchableOpacity>
      <TouchableOpacity style={styles.textContainer} onPress={customAlert}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </TouchableOpacity>
      <TouchableOpacity style={styles.textContainer} onPress={customAlert}>
        <Text style={styles.textStyle}>영역을 충분히 갖는 텍스트 입니다!</Text>
      </TouchableOpacity>
    </ScrollView>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  textContainer: {
    height:100,
    borderColor:'#000',
    borderWidth:1,
    borderRadius:10,
    margin:10,
  },
  textStyle: {
    textAlign:"center"
  }
});

 

 

위와 같이 영역에서 버튼처럼 기능구현이 가능하다

 


 

<Image> 태그 활용해서 앱화면에 이미지를 노출하자

  • 내부 폴더 안에있는 이미지를 사용하는 방법이 있다
  • 여러 속성을 사용해서 이미지를 삽입한다
  • source, resizeMode, style등 여러 속성을 활용할 수 있다.
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={"repeat"}
        style={styles.imageStyle}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    justifyContent:"center",
    alignContent:"center"
  },
  imageStyle: {
    width:"100%",
    height:"100%",
    alignItems:"center",
    justifyContent:"center"
  }
});

 

 

resizeMode를 repeat로 부여했다

 

 

  • 외부 이미지 링크를 사용하는 방식도 있다.
  • 위와 다르게 resizeMode에 repeat을 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}>
      <Image 
        source={{uri:'https://images.unsplash.com/photo-1424819827928-55f0c8497861?fit=crop&w=600&h=600%27'}}
        resizeMode={"cover"}
        style={styles.imageStyle}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    justifyContent:"center",
    alignContent:"center"
  },
  imageStyle: {
    width:"100%",
    height:"100%",
    alignItems:"center",
    justifyContent:"center"
  }
});

 

resizeMode를 cover로 부여했다

 

 

앱 화면을 구현하기위해 기초적인 태그들을 정리해보았다

앞으로 React Native를 활용해서 Expo와 같이 구현한다

 Expo에 대한 장점과 단점은 분명하며 어떤 앱을 구현할때 Expo가 유리할지도 생각해보아야겠다

앞으로 어떤앱이 탄생할지 계속해서 만들어보자

 

728x90
반응형
728x90
반응형

이전 포스팅에서 GraphQL API 구축을 하였다

 

그 코드를 다시 리팩토링 하여 axios 밑 비동기 방식으로 변경하였다

 

그리고 두개의 쿼리를 작동시켜 데이터를 가져오는 방법을 확인 해보자

 

 


db.js

import axios from "axios";
const BASE_URL = "https://yts.am/api/v2/";        // 기본적인 api url을 지정하고 
const LIST_MOVIES_URL = `${BASE_URL}list_movies.json`;  
				// 그 다음은 기능적으로 필요한 url을 개별적으로 관리한다
const MOVIE_DETAILS_URL = `${BASE_URL}movie_details.json`;
const MOVIE_SUGGESTIONS_URL = `${BASE_URL}movie_suggestions.json`;

export const getMovies = async (limit, rating) => { 
			// async await는 자바스크립트의 비동기 처리 패턴중 가장 최근에 나온 문법으로
    const {          // 비동기처리 방식인 콜백함수와 프로미스의 단점을 보완하는 방법이다
        data: {
            data: { movies }
        }
    } = await axios(LIST_MOVIES_URL, {  // 기존  node-fetch를 axios로 변경하여 사용하였다
        params: {
            limit,
            minimum_rating: rating
        }
    });
    return movies;
};

export const getMovie = async id => {	// 영화한개의 정보를 가져오는 함수
    const {
        data: {
            data: { movie } 
        }
    } = await axios(MOVIE_DETAILS_URL, {
        params: {
            movie_id: id
        }
    });
    return movie;
};

export const getSuggestions = async id => { // 추천 영화 검색해서 가져온다
    const {
        data: {
            data: { movies }
        }
    } = await axios(MOVIE_SUGGESTIONS_URL, {
        params: {
            movie_id: id
        }
    });
    return movies;
};

 

위와 같이 변경하였다

 

이제 그에 맞게 스키마를 재정의 하자

 

 


schema.graphql

type Movie {
    id: Int!
    title: String!
    rating: Float
    description_intro: String
    language: String
    medium_cover_image: String
    genres: [String]
}

type Query {
    movies(limit: Int, rating: Float): [Movie]!
    movie(id: Int!): Movie
    suggestions(id: Int!): [Movie]!
}

 

 

스키마에 suggestions를 추가하여 쿼리를 호출할 수 있게 한다

 


resolvers.js

import { getMovies, getMovie, getSuggestions } from "./db";

const resolvers ={
    Query: {
        movies: (_, { rating, limit }) => getMovies(limit, rating), 
        			// resolvers 함수는 스키마에 정의되어있는 쿼리의 함수들을 참조한다
        movie: (_, { id }) => getMovie(id),                     
        			// resolvers 함수에 db의 함수를 참조하여 추출 데이터를 가지고 오게된다
        suggestions: (_, { id }) => getSuggestions(id)      
        			// Query의 키들은 직접적인 쿼리문을 호출할때 사용한다
    }
};

export default resolvers;

 

나머지 파일들은 기존 셋팅과 동일하며

 

변경된 코드들을 실행을 하게 된다면 밑에와 같이 출력이 된다

 

 

 

 

 

이렇게 변경한 코드로 React를 적용하여 만들어보자!

 

 

 

 

 

2020/06/26 - [GraphQL/GraphQL 활용 서버구축 실습] - GraphQL API로 데이터 정보 가져오기

 

GraphQL API로 데이터 정보 가져오기

이전 포스팅에서 GraphQL로 간단한 정보를 가져왔다 이제는 영화 오픈 API를 통해 정보를 가져와보자 우선 index.js에 GraphQL를 활용해서 서버를 구축하고 맵핑을 시작하자 이것은 이전포스팅과 동일�

tantangerine.tistory.com

 

728x90
반응형
728x90
반응형

이전 포스팅에서  GraphQL로 간단한 정보를 가져왔다

 

이제는 영화 오픈 API를 통해 정보를 가져와보자

 

우선 index.js에 GraphQL를 활용해서 서버를 구축하고 맵핑을 시작하자

 

이것은 이전포스팅과 동일하지만 다시한번 작성해보자

 


index.js

import { GraphQLServer } from "graphql-yoga";
import resolvers from "./graphql/resolvers"

const server = new GraphQLServer({
    typeDefs: "graphql/schema.graphql", // 스키마정의가 되어있는 곳을 Defs로 둔다
    resolvers   // 결과 값을 실행할곳을 성정한다 단지 이 4줄로 끝이다
});

server.start(() => console.log("Graphql server Running"));

 

그리고 가져올 영화 정보가 어떤 타입인지 지정해주어야한다

 

영화정보를 가져올때 어떠한 형식인지 지정해주어야 하는것이다

 


schema.graphql

type Movie {
    id: Int!
    title: String!
    rating: Float!
    summary: String!
    language: String!
    medium_cover_image: String!
}                   

type Query {       
    movies(limit: Int, rating: Float): [Movie]!      
}

 

그리고 db.js를 만드는데 여기서는 오픈 API를 연결한다

 

db.js에는 url주소가 필요하며 그리고 url에 쿼리스트링이 있다면 그 쿼리스트링을 동적으로 변수처리해서 

 

조건을 변경할 수 있다

 


db.js

import fetch from "node-fetch";
const API_URL = "https://yts.am/api/v2/list_movies.json?";

// Node.js에서 fetch를 할때 필요하다 node-fetch를 설치하자

export const getMovies = (limit, rating) => {
    let REQUEST_URL = API_URL;
    if (limit > 0) {
        REQUEST_URL += `limit=${limit}`;
    }
    if (rating > 0) {
        REQUEST_URL += `&minimum_rating=${rating}`;
    }
    return fetch(REQUEST_URL)
      .then(res => res.json())
      .then(json => json.data.movies);
}

 

그리고 resolvers.js를 만들어서 Query문을 작성해서 오픈API에서 가져올 정보를 핸들링할 수 있다

 


 resolvers.js

import { getMovies } from "./db";

const resolvers ={
    Query: {
        movies: (_, { rating, limit }) => getMovies(limit, rating)
    }
};

export default resolvers;

 

이러한 결과는 아래와 같이 나오게된다

 

영화 API 

 

다음 포스팅은 더 많은 데이터 조작을 하고 여러가지 함수활용을 해보겠습니다!

 

 

728x90
반응형
728x90
반응형

Clipboard Events

이벤트 이름 :onCopy , onCut, onPaste

속성 : DOMDataTransfer clipboardData

 

Composition Events

이벤트 이름 : onCompositionEnd ,onCompositionStart, onCompositionUpdate

속성 : string data

 

Keyboard Events

이벤트 이름 :onKeyDown, onKeyPress, onKeyUp

속성 :

boolean altKey

number charCode

boolean ctrlKey

boolean getModifierState(key)

string key

number keyCode

string locale

number location

boolean metaKey

boolean repeat

boolean shiftKey

number which

이 key속성은 DOM Level 3 Events spec에 설명 된 값 중 하나를 사용할 수 있습니다 .

 

Focus Events

이벤트 이름 :onFocus , onBlur

이러한 포커스 이벤트는 폼 요소뿐만 아니라 React DOM의 모든 요소에서 작동합니다.

속성 : DOMEventTarget relatedTarget

 

Form Events

이벤트 이름 : onChange, onInput, onInvalid, onSubmit

onChange 이벤트에 대한 자세한 정보는 양식을 참조하십시오 .

 

Mouse Events

이벤트 이름 :

onClick, onContextMenu, onDoubleClick, onDrag, onDragEnd, onDragEnter, onDragExit,

onDragLeave, onDragOver, onDragStart, onDrop, onMouseDown, onMouseEnter, onMouseLeave,

onMouseMove, onMouseOut, onMouseOver, onMouseUp

 

onMouseEnteronMouseLeave이벤트는

하나가 아닌 일반 버블의 입력되는 왼쪽이 되는 요소로부터 전파하고 캡처 단계가 없습니다.

 

속성 :

boolean altKey

number button

number buttons

number clientX

number clientY

boolean ctrlKey

boolean getModifierState(key)

boolean metaKey

number pageX

number pageY

DOMEventTarget relatedTarget

number screenX

number screenY

boolean shiftKey

 

Pointer Events

이벤트 이름 :

onPointerDown, onPointerMove, onPointerUp, onPointerCancel, onGotPointerCapture,

onLostPointerCapture, onPointerEnter, onPointerLeave, onPointerOver, onPointerOut

onPointerEnteronPointerLeave이벤트는 하나가 아닌 일반 버블의 입력되는 왼쪽되는 요소로부터 전파하고 캡처 단계가 없습니다.

 

속성 :

W3 spec에 정의 된대로 포인터 이벤트 는 다음 속성을 사용하여 마우스 이벤트 를 확장 합니다.

number pointerId

number width

number height

number pressure

number tangentialPressure

number tiltX

number tiltY

number twist

string pointerType

boolean isPrimary

브라우저 간 지원에 대한 참고 사항 :

포인터 이벤트는 모든 브라우저에서 아직 지원되지는 않습니다

(이 기사를 작성할 당시 지원되는 브라우저에는 Chrome, Firefox, Edge 및 Internet Explorer가 포함됨).

표준 준수 폴리 필이의 번들 크기를 크게 늘리기 때문에

React는 의도적으로 다른 브라우저에 대한 지원을 폴리 필하지 않습니다 react-dom.

응용 프로그램에 포인터 이벤트가 필요한 경우 타사 포인터 이벤트 폴리 필을 추가하는 것이 좋습니다.

 

Selection Events

이벤트 이름 : onSelect

 

Touch Events

이벤트 이름 : onTouchCancel onTouchEnd onTouchMove onTouchStart

속성 :

boolean altKey

DOMTouchList changedTouches

boolean ctrlKey

boolean getModifierState(key)

boolean metaKey

boolean shiftKey

DOMTouchList targetTouches

DOMTouchList touches

 

UI Events

이벤트 이름 : onScroll

속성 :

number detail

DOMAbstractView view

 

 

onScroll

이벤트 이름 : onWheel

속성 :

number deltaMode

number deltaX

number deltaY

number deltaZ

 

Media Events

이벤트 이름 :

onAbort, onCanPlay, onCanPlayThrough, onDurationChange, onEmptied, onEncrypted,

onEnded, onError, onLoadedData, onLoadedMetadata, onLoadStart, onPause, onPlay,

onPlaying , onProgress, onRateChange, onSeeked, onSeeking, onStalled, onSuspend,

onTimeUpdate, onVolumeChange, onWaiting

 

 

Image Events

이벤트 이름 :onLoad, onError

 

 

Animation Events

이벤트 이름 : onAnimationStart, onAnimationEnd, onAnimationIteration

속성 :

string animationName

string pseudoElement

float elapsedTime

 

 

Transition Events

이벤트 이름 : onTransitionEnd

속성 :

string propertyName

string pseudoElement

float elapsedTime

 

 

Other Events

이벤트 이름 :onToggle

 

 

728x90
반응형
728x90
반응형

# final

위치 : 마지막이라는 의미

의미 : 클래스 앞(상속금지), 메서드 앞(overriding 금지), 변수 앞(재할당 금지)

 

 

 

final 클래스 앞에 선언될 때 예문


final class A{ //final은 class에서 상속할 것이 없을 때 확장(상속) 금지를 선언할 때 사용한다

  static int a=100; //옆에 예문처럼 static만 선언되어있다면 상속할 필요가 없으므로

  static int b(){ return 200; }// final을 선언해서 상속하는 것을 막아야 한다

  } //static은 공용처럼 사용할 수 있으며 어떤 변수가 초기화하거나 재할당하게 되면
	//그 값은 독자적인 값으로 여러 객체생성을 하면 그 값은 한 개의 값으로 선언된다

class B extends A{ 

  void c(){

  System.out.println(a);

  }

}

class C{

  public static void main(String args[]){

    B o1=new B(); o1.a=300; = A.a=300; //가독성을 위해 변경해야한다

    B o2=new B(); o2.c();

  }

}


 

 

final 변수 앞에 선언될 때 예문


class A{

  final int num;



  A(int n){

    num=n; // 생성자에서 로컬변수의 최초 재할당은 가능하다.

    num=300; // 컴파일에러

  }

  void a(){

  num=400; // 컴파일에러

  }

}

interface A{ //자동으로 접근제어자 선언됨

  void abc(); 
  
} //interface를 선언하게되면 그 클래스 해당하는 메서드는 static final void abc();라는 형식이

숨겨져 있다 그래서 범위가 정해지고 public > protected > default > private

class B implements A{

  public void abc(){ //앞에는 public을 꼭 선언해야 오버라이딩을 할 수 있다

  } //그리고 interface를 선언하게되면 개체생성을 하지 못하고 구현개체를 개별로 선언해주고

} //부모상족자로 interface 클래스를 선언하여 interface가 가지고있는 메서드를 구현 개체에

//오버라이딩을 해서 구현하게된다

 

 

 

# 다형적변수

다형적 변수는 상속(확장) 관계에서만 허용되며, 자식 클래스의 오버라이딩된 메서드만 접근할 수 있다

 

 

추상클래스에서 추상메서드는 실행 바디를 생성할 수 없다 아래의 문장을 확인하자

 


abstract class Animal{ 

  abstract void sound(); //실행문인 {}가 제외되었다는것을 알 수 있다

  abstract void sound(); //이때 추상 클래스 추상 메서드를 선언하여 강제로 오버라이딩을 하게 한다

} //그 이유는 추상 클래스의 추상 메서드가 선언되면 상속자의 시그니쳐와 같은 형태의


class Dog extends Animal{ //오버라이딩을 해야 컴파일에러가 발생하지 않기 때문이다

  void sound(){ System.out.println("멍멍"); } //그래서 자식 상속자 클래스를 
  								// 작업하는 사람의 실수를 미연에 방지할 수 있다
}


class Duck extends Animal{// 다형적변수와 추상 클래스의 추상메서드는 반드시 함께 생각해야만 한다

  void sound(){ System.out.println("꽥꽥"); }

}


class Cat extends Animal{

  void sound(){ System.out.println("야옹"); }

}


class Sound{

  static void test(Animal s){

  s.sound();

  }
}


class A{

  public static void main(String[] args){

    Dog dog=new Dog();

    Duck duck=new Duck();

    Cat cat=new Cat();

    Sound.test(dog);

    Sound.test(duck);

    Sound.test(cat);

  }
}


 

# abstract

 

의미 : 추상적이라는 의미

위치 : 클래스 앞, 메서드 앞

 

추상 클래스는 객체를 생성할 수 없다

 


abstract class A{ 

  //클래스 간 확장(상속) 관계일 때 클래스 B도 추상 클래스를 선언해야

  int a=100; 		// 컴파일에러가 발생하지 않는다

} 			//또 한 추상 클래스가 선언된 클래스는 상속(확장) 관계인 클래스는

class B{			// 메서드 오버라이딩을 해야 컴파일 오류를 막을 수 있다

  public static void main(String[] args){

    A o=new A();

    System.out.println(o.a);

  }
}

--------------------------------------------------------

abstract class A{

  abstract void abc();

  void def(){ System.out.println(200); 
  
  }
}

abstract class B extends A{

  void def(){System.out.println(100); 
    
}




반응형

# 참조형간의 형변환

 

다형적 변수로 자식의 오버라이딩 되지 않은 메서드를 호출할 때 형변환을 사용한다. (상속 관계에서만 적용) 예문 확인

 


class A{

}

class B extends A{

  void abc(){ 
  
  	System.out.println(1); 

}


class C{

  public static void main(String[] args){

    B o1=new B();

    o1.abc(); // 1

    A o2=o1;

    o2.abc(); // 컴파일에러

    B o3=(B)o2;

    o3.abc(); // 1

  }
}

 


 

#수치형간의 형변환(정수, 실수, 문자)

 

 

byte(1) < short, char(2)< int(4)< long(8) < float(4) < double(8)

 

 


 

int a=10;

byte b=a; // 컴파일에러



byte a=10;

int b=a; // 자동형변환



double a=3.5;

int b=a; // 컴파일에러



double a=3.5;

int b=(int)a; // 강제형변환



int a=10; // 0이28개1010

byte b=10; // 00001010



char a='A';

char b=65;

char c='\u0041';

System.out.println(a);

System.out.println(b);

System.out.println(c);



System.out.println('A'+1); // 66

System.out.println("A"+1); // A1



float a=3.5; // 컴파일에러

float b=3.5F;

int c=5L; // 컴파일에러

int d=3D; // 컴파일에러




 

값자체를 의미할때 컴퓨터언어에서는 리터럴(literal) ==>

숫자D --> double형

숫자F --> float형

숫자L --> long형

 

0b숫자 --> 2진수표현

0숫자 --> 8진수표현

0x숫자 --> 16진수표현

 

 

[ex] 10진수65를 2진수로 표현하면?

단, java.lang.Integer클래스의 toBinaryString메서드를 이용한다.

 


[an]

class A{

  public static void main(String... args){

    String s=Integer.toBinaryString(65);

    System.out.println(s); // 01000001

  }

}





[ex] 10진수65를 16진수로 표현하면?

단, java.lang.Integer클래스의 toHexString메서드를 이용한다.



[an]

class A{

  public static void main(String... args){

    String s=Integer.toHexString(65);

    System.out.println(s); // 41

  }
}
728x90
반응형

+ Recent posts

Powered by Tistory, Designed by wallel