728x90
반응형

 

 

이번에는 구글 파이어 베이스의 Cloud Firestore 데이터 추가 기능을 구현해보겠습니다

 추가할 때 이미지도 같이 저장해보도록 하겠습니다

 

아래의 목차와 같이 진행하겠습니다

 

  1. Storage 설정 및 폴더 추가하기
  2. App 내에서 이미지 데이터 컨트롤하기
  3. Stroage에 이미지 저장하기
  4. Cloud Firestore에 데이터 추가하기

 

우선 파이어 베이스의 이미지를 파일 저장소(Storage) 설정부터 하겠습니다

 

 


Storage 설정 및 폴더 추가

폴더를 추가하고 보안설정을 진행하도록 하겠습니다

 

 

파일저장소-설정
Storage 설정 및 폴더 추가

 

 

Rules 탭을 클릭해서

allow read, write로 설정하여

읽고, 쓰기를 가능하게 합니다

 

 

파일저장소-보안설정
파일저장소 보안 설정하기

 

 

이제는 이미지를 저장할 파일 저장소의 폴더 추가 및 설정을 끝냈습니다

 

 


App 내에서 이미지 데이터 컨트롤 하기

expo-image-picker 라이브러리를 설치합니다

 

사진을 촬영해서 바로 앱에 데이터를 전달하여 이미지를 저장하는 방법

앱 내의 사진첩을 접근해서 이미지 데이터를 불러와 저장하는 방법을 알아보겠습니다

 

 

새탭열기
마우스 우 클릭 화면

 

 

그 방법은 아래의 포스팅에 자세히 설명이 되어있습니다

포스팅을 클릭할 때 마우스 우 클릭해서  새 탭에서 링크 열기를 선택하시면 더 편하게 볼 수 있습니다

 

그럼 아래의 포스팅을 클릭해봅시다!

 

 

2022.07.29 - [Mobile/React_Native] - React Native X Expo 이미지 데이터 expo-image-picker로 이미지 업로드 구현하기

 

React Native X Expo 이미지 데이터 expo-image-picker로 이미지 업로드 구현하기

이미지 업로드 기능 구현하기 앱에서 이미지나 사진을 업로드할 경우 두가지 방법이있습니다 첫번째는 사진을 찍어서 업로드를 하는 방법 두번째는 자신의 사진첩에서 불러와 업로드 하는 방

tantangerine.tistory.com

 


 

반응형

 


Storage에 이미지 저장하기

 

아래와 같이 화면이 구성되어있다고 가정합시다

 

 

이미지데이터저장
이미지 데이터 저장

 

 

  const pickImage = async () => {
    console.log('이미지 선택');
    let imageData = await ImagePicker.launchImageLibraryAsync({
      mediaTypes: ImagePicker.MediaTypeOptions.All,
      allowsEditing: true,
      aspect: [4, 4],
      quality: 1,
    });
    if(imageData.uri){
      setImageUri(imageData.uri ? imageData.uri : '');
    }
  };

 

 

위와 같이 선언된 함수를 호출하여 이미지 사진첩 내 이미지의 데이터를 가져와서 setImageUri에 저장합니다

또 한, 미리 보기 기능이 구현되어있다면 저장할 때 imageData.uri가 있을 경우에만 저장하도록 합니다

 

 

 

 

등록버튼클릭
등록버튼 클릭이미지

 

등록버튼을 클릭하게 되면 아래와 같은 함수가 호출이 됩니다

 

이때 중요한 것은 blob형식으로 변경해야지만 최종적으로 파이어 베이스 storage에 업로드할 수 있습니다

 

사이드바에 공식문서를 참조하시면 더 많은 정보를 확인할 수 있습니다

 

blob 객체는 파일류의 변하지 않는 미가공 데이터를 나타내며, 텍스트와 이진 데이터 형식으로 읽을 수 있습니다

 

 

const upload = () => {
    confirmAlert('게시글을 등록하시겠습니까?', async () => {
      console.log('업로드 준비중!');
      if(!imageUri){
        Alert.alert('이미지를 등록해주세요.');
        return;
      }
      if(!title){
        Alert.alert('제목을 입력해주세요');
        return;
      }
      if(!content){
        Alert.alert('내용을 입력해주세요');
        return;
      }
      if(!currentUser.uid){
        Alert.alert('로그인이 필요합니다');
        return;
      }
      const currentUser = firebase.auth().currentUser;
      let date = new Date();
      let getTime = date.getTime();
      let data = {
        title: title,
        author: currentUser.email,
        desc: content,
        image: image,
        date: getTime,
        uid: currentUser.uid,
      };
      const response = await fetch(imageUri);
      const blob = await response.blob();
      const imageUrl = await imageUpload(blob, getTime);
      data.image = imageUrl;
      console.log(data);
      let result = await addDiary(data);
      if (result) {
        Alert.alert('글이 성공적으로 등록되었습니다!');
        setTitle('');
        setContent('');
        setImage(tempImage);
        setImageUri('');
      }
    })
  };

 

 

blob데이터
Blob 데이터 가져오기

 

 

fetch를 활용해서 주소를 실행시켜 결괏값을 가져와 blob함수를 실행하여 그 데이터 값을 storage에 저장하게 됩니다

 

 

 

그렇게 호출된 imageUpload에서 아래와 같이 실행하게 됩니다

blob과 데이터를 매개변수로 받아 파일 저장소(storage)에 저장하게 됩니다

저장 후   snapshot.ref.getDownloadURL()를 호출하여 storage에 저장된 url주소를 불러옵니다

그 불러온 url주소를 reurn 하여 cloud firestore에 저장합니다

 

 

export async function imageUpload(blob, date) {
  const storageRef = firebase
    .storage()
    .ref()
    .child('diary/' + date);
  const snapshot = await storageRef.put(blob);
  const imageUrl = await snapshot.ref.getDownloadURL();
  blob.close();

  return imageUrl;
}

 


Cloud firestore에 데이터 추가하기

 

 

addDiary호출하기
addDiary 호출

 

 

위와 같이 return값을 기본 Object객체에 추가하여 addDiary의 매개변수를 할당하여 함수 호출을 합니다

그리고 firebase.firestore() 함수, db.collection(). doc.(). set()의 두 가지 함수를 호출하여

diary라는 데이터 베이스 테이블 생성과 data의 객체 값들을 cloud firestore에 추가합니다

 

 

export async function addDiary(content) {
  try {
    const db = firebase.firestore();
    await db.collection('diary').doc(content.date + "D").set(content);
    return true
  } catch (err) {
    Alert.alert("글 작성에 문제가 있습니다! ", err.message)
    return false
  }
}

 

 

아래와 같이 파이어 스토어에 저장된 모습을 확인할 수 있습니다

collection('diary') // 테이블을 만들게 되면서 diary를 만들면서 없을 때에는 추가를 하게 됩니다

. doc(content.date + "D") // 저장한 날짜를 가져와 'D'를 붙여서 저장합니다 그것이 테이블의 PK KEY가 됩니다

하지만 위의 방식보다는 doc(content.date + "_" + content.author) 이 방식으로 변경하는 것이 더 유니크한 값이 되지 않을까 생각합니다 여러 유저들이 들어와서 이미지를 동시에 클릭한다면 분명 오류가 발생할 것이라 생각합니다

. set(content); // content객체의 값들은 아래에 이미지에서 확인할 수 있습니다

 

cloud-firestore
클라우드 파이어스토어 저장모습

 


 

이렇게 cloud firestore에 데이터 저장하는 방법과 파일 저장소(Storage)에 이미지를 저장하는 방법을 알아보았습니다

사이드바에 파이어 베이스 관련 공식 문서가 있으니 참고하세요

 

IT 개발 공부는 끝이 없기에 항상 공부를 해야 하는 직종이지요 하지만 포기하지 마시고 끝까지? 끝이 있을지는 모르겠지만 하시길 바랍니다

 

우리들의 대모험은 끝나지 않았습니다 그럼 파이팅 하시고 다음 포스팅도 기대해주세요 감사합니다

 

 

 

 

728x90
반응형
728x90
반응형

이미지 업로드 기능 구현하기

 

 

앱에서 이미지나 사진을 업로드할 경우 두가지 방법이있습니다

 

첫번째는 사진을 찍어서 업로드를 하는 방법

두번째는 자신의 사진첩에서 불러와 업로드 하는 방법

 

이 두가지를 방법을 구현할 수 있는 기능을 알아보도록 하겠습니다

 

공식문서 사이드바에서

공식문서 & 유용한 툴 목차를 보자

 

Expo-image-picker
이미지 픽커 공식문서

 

 

expo-image-picker 라이브러리는 설치

사진 접근 권한 알림 팝업 기능 구현

launchImageLibraryAsync를 사용해서 사진첩에 접근해서 사진을 불러옵니다

 

 

expo-image-picker 라이브러리는 설치하겠습니다

 

expo install expo-image-picker

 


 

권한 허용 함수 구현하기

 

 

사진을 등록할 경우에

접근권한을 물어보는 것이 좋을 것같습니다 

 

아래와 같이 함수를 구현하여

사진을 업로드 할 경우 권한이 가능한지에 대해

true, false를 반환하여 

값에 따라 다음 절차를 진행 여부를 판단합니다

 

const getPermission = async () => {
    if (Platform.OS !== 'web') { // is web or mobile?
          const {
            status,
          } = await ImagePicker.requestMediaLibraryPermissionsAsync();
          if (status !== 'granted') {
            alert('게시글을 업로드하려면 사진첩 권한이 필요합니다.');
            return false
          }
          return true
    }
};

 

 

위의 코드에서 ImagePicker.requestMediaLibraryPermissionsAsync();

함수를 사용해서 팝업 창이 노출되면서 허용 권한을 설정할 수 있게됩니다

그리고 한번 허용되면 다음부터는 팝업이 노출되지 않을겁니다

 

그럼 권한 허용이 되면

다음 함수를 실행합니다

 


 

 

 

반응형

 

 


 

디바이스 내 사진첩 사진 데이터 불러오기, 찍은 사진 데이터 불러오기

 

 

그럼 아래와 같이 코드를 구현합니다

이때 launchImageLibraryAsync를 사용해서 사진첩에 접근해서 사진을 불러옵니다

그리고 사진을 선택하면 함수의 리턴값으로 이미지 데이터를 받을 수 있습니다

 

또 한, launchCameraAsync 함수를 사용하면

직접 사진을 찍어서 앱 내부로 데이터를 가져올 수 있습니다

 

아래와 같이 함수를 구현합니다

 

 

const pickImage = async () => {
    console.log('이미지 선택');
    let imageData = await ImagePicker.launchImageLibraryAsync({
        mediaTypes: ImagePicker.MediaTypeOptions.All, // 이미지 타입을 지정할 수 있다
        allowsEditing: true, // 사진을 수정허용 여부을 지정한다.
        aspect: [4, 4], // 사진의 비율을 정할 수 있다.
        quality: 1, // 현재 용량을 줄이고 높일 수 있다.
    });
    console.log('이미지 데이터: ', imageData);
};

 

 

사진을 불러올때 여러가지 옵션이 있습니다

용량을 줄이거나 사진비율을 정하거나 수정을 허용여부를 정할수도 있습니다

아래에 더 자세하게 설명해놓았습니다

확인해보세요!~

 

 

 

ImagePickOption

allowsEditing
(optional)
boolean 이미지를 선택한 후 편집할 UI를 표시할지 여부입니다. Android에서는 사용자가 이미지를 자르고 회전할 수 있고 iOS에서는 단순히 이미지를 자를 수 있습니다.
Default: false
allowsMultipleSelection
(optional)
boolean Only for: Web

한 번에 여러 미디어 파일을 선택할 수 있는지 여부입니다.
aspect
(optional)
[number, number] [x, y]사용자가 이미지를 편집할 수 있는 경우( 를 전달하여) 유지할 종횡비를 지정하는 두 개의 항목이 있는 배열입니다 allowsEditing: true. iOS에서는 자르기 사각형이 항상 정사각형이기 때문에 Android에서만 적용할 수 있습니다
base64
(optional)
boolean Base64 형식의 이미지 데이터도 포함할지 여부입니다.
exif
(optional)
boolean 이미지에 대한 EXIF ​​데이터도 포함할지 여부입니다. iOS에서 EXIF ​​데이터는 카메라 케이스에 GPS 태그를 포함하지 않습니다.
mediaTypes
(optional)
MediaTypeOptions 선택할 미디어 유형을 선택합니다.
Default: ImagePicker.MediaTypeOptions.Images
presentationStyle
(optional)
UIImagePickerPresentationStyle Only for: iOS

사진/동영상을 촬영하는 동안 보기를 사용자 지정 하려면 프레젠테이션 스타일 을 선택하세요 
Default: ImagePicker.UIImagePickerPresentationStyle.Automatic
quality
(optional)
number 에서 까지 압축 품질을 지정 0합니다 1. 0작은 크기를 위한 1압축을 의미하고 최대 품질을 위한 압축을 의미합니다.
videoExportPreset
(optional)
VideoExportPreset Only for: 
iOS 11+

선택한 비디오를 압축하는 데 사용할 사전 설정을 지정합니다.
Default: ImagePicker.VideoExportPreset.Passthrough
videoMaxDuration
(optional)
number 비디오 녹화의 최대 지속 시간(초). 제한 을 0비활성화하도록 설정합니다. 기본값은 0(무제한)입니다.
  • iOS 에서 allowsEditing가 로 설정된 true경우 최대 지속 시간은 10분으로 제한됩니다. 이 제한은 0값이 지정되거나 지정되지 않은 경우 자동으로 적용됩니다.
  • Android 에서 이 옵션의 효과는 설치된 카메라 앱의 지원에 따라 다릅니다.
  •  에서 이 옵션은 효과가 없습니다. 제한은 브라우저에 따라 다릅니다.
videoQuality
(optional)
UIImagePickerControllerQualityType Only for: 
iOS

녹화된 비디오의 품질을 지정합니다. 기본값은 장치에 사용할 수 있는 최고 품질입니다.

Default: ImagePicker.UIImagePickerControllerQualityType.High

 

 

속성을 지정하고 함수를 호출하면 아래와 같이 데이터를 받을 수 있습니다

 

 

사진불러오기
이미지 데이터

 

 

이 데이터를 받아서 클라우드에 저장하면 됩니다

그 방법은 클라우드에 맞는 여러방법들이 있을것이니

그에 맞게 기능구현이 필요할 것 같습니다

 

이렇게 expo-image-picker를 구현해보있습니다

그럼 오늘도 이렇게 글을 마치겠습니다

다음 포스팅도 기대해주시고~

 

앞으로 같이 계속 공부해보아요~

 

 

 

 

728x90
반응형
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
반응형

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
반응형

 

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

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

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

 

그래서 스타일링을 간편하게 도와주는 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
반응형

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

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

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

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

 

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

리얼 타임 데이터베이스는 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.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
반응형

+ Recent posts

Powered by Tistory, Designed by wallel