728x90

리액트 네이티브를 공부하면서 네이티브모듈을 사용해보고 싶어졌다.

사용하기 위해서 코틀린 설정을 해봐야하는데 너무 오래걸렸다. 기록기록

네이티브 모듈을 사용하려면 모듈 생성 -> 패키지 등록 순으로 이루어진다.

먼저 react native 사이트에 있는 setting 방법으로 react-native cli 를 이용해서 프로젝트를 생성해 준다. 

안드로이드 스튜디오와 xcode 등 설벙은 공식 사이트를 참고했다.

https://reactnative.dev/docs/environment-setup

실행 환경은

MacOS m1

jdk 11

react-native 0.71 을 사용했다.

npx react-native init <프로젝트명>

으로 프로젝트를 생성해 준다.

 

 

 

1. android/build.gradle

먼저 생성된 프로젝트에서 android 디렉토리에 있는 build.gradle에 몇가지를 추가해준다.

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    ext {
        buildToolsVersion = "33.0.0"
        minSdkVersion = 21
        compileSdkVersion = 33
        targetSdkVersion = 33
        kotlinVersion = "1.7.0"
        // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP.
        ndkVersion = "23.1.7779620"
    }
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
        classpath("com.android.tools.build:gradle:7.3.1")
        classpath("com.facebook.react:react-native-gradle-plugin")
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
    }
}

kotlinVersion을 1.7.0으로 해주고, dependencies에 classpath를 추가해준다.

 

2. android/app/build.gradle

다음으로는 adroid 안에 있는 app 안에 build.gradle 에 몇가지를 추가해준다.

apply plugin: "kotlin-android"
dependencies {
	implementation "org.jetbrains.kotlin:kotlin-stdlib"
   }

2 코드를 각각 추가해 줬다.

 

3. module 생성

main/java/com/exam 디렉토리에 calculator 디렉토리를 만들고 CalculatorModule.kt파일을 추가해 줬다.

package com.exam.calculator
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.Callback

class CalculatorModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {

    override fun getName():String="CalculatorModule"

    @ReactMethod
    fun add(a:Double,b:Double,callback:Callback){
        var c:Double = a+b
        callback.invoke(c)
    }
}

reactContext를  생성자 인자값으로 받고,ReactContextBaseJavaModul을 상속받는 CalculatorModule class를 만들어 줬다.  getName() 메소드를 override 했다. getName은 react-native js 단에서 사용할 모듈 이름이다. 클래스 이름과 같이 지어줬다.

@ReactMethod 어노테이션을 달아주면, react-native 단에서 함수로 불러 사용할 수 있다.

 

add 메소드를 만들고 , Double 타입의 인자 a,b와 Callback 을 받아 준다.

a+b의 값을 가지는 c 변수를 callback의 invoke 메소드에 넣어준다.

 

만들어 둔 module을 react-native에서 사용하기 위해서는 다음으로 Package 묶어서 보내줘야한다고한다.

package com.exam.calculator

import android.view.View
import com.facebook.react.ReactPackage
import com.facebook.react.bridge.NativeModule
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.uimanager.ReactShadowNode
import com.facebook.react.uimanager.ViewManager

class CalculatorPackage : ReactPackage {

    override fun createViewManagers(
        reactContext: ReactApplicationContext
    ): List<ViewManager<*,*>> = emptyList()

    override fun createNativeModules(
        reactContext: ReactApplicationContext
    ): MutableList<NativeModule> = listOf(CalculatorModule(reactContext)).toMutableList()
}

CalculatorPackage class 를 ReactPackage를 상속받아 만들어 주고 createViewManagers 와 createNativeModules를 override해서 정의 해준다. 만든 모듈은 createNativeModules에 들어 간다.

마지막으로 MainApplication.java 에서 패키지로 등록해준다.

package com.exam;

import android.app.Application;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint;
import com.facebook.react.defaults.DefaultReactNativeHost;
import com.facebook.soloader.SoLoader;
import java.util.List;
import com.exam.calculator.CalculatorPackage;

public class MainApplication extends Application implements ReactApplication {

  private final ReactNativeHost mReactNativeHost =
      new DefaultReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
          return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
          @SuppressWarnings("UnnecessaryLocalVariable")
          List<ReactPackage> packages = new PackageList(this).getPackages();
          // Packages that cannot be autolinked yet can be added manually here, for example:
          // packages.add(new MyReactNativePackage());
          packages.add(new CalculatorPackage());
          return packages;
        }

        @Override
        protected String getJSMainModuleName() {
          return "index";
        }

        @Override
        protected boolean isNewArchEnabled() {
          return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
        }

        @Override
        protected Boolean isHermesEnabled() {
          return BuildConfig.IS_HERMES_ENABLED;
        }
      };

  @Override
  public ReactNativeHost getReactNativeHost() {
    return mReactNativeHost;
  }

  @Override
  public void onCreate() {
    super.onCreate();
    SoLoader.init(this, /* native exopackage */ false);
    if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
      // If you opted-in for the New Architecture, we load the native entry point for this app.
      DefaultNewArchitectureEntryPoint.load();
    }
    ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
  }
}

CalculatorPackage를 import 해주고 getPackages() 메소드안에 Package.add() 의 인자 값으로 new 로 생성해 넘겨준다.

 

이렇게 만들어진 모듈을 react-native에서 NativeModules를 먼저 import한뒤 NativeModules.모듈 로 사용할수 있다 .이때 모듈은 getName() 에서 정의해준 모듈 이름으로 사용가능하다. 

import {NativeModules} from 'react-native';
const {CalculatorModule} = NativeModules;
  CalculatorModule.add(1, 2, (sum: number) => {
    console.log(sum);
  });

그렇게 심도있게 알지는 못했지만 어쨌든 원하는 결과 값이 나온것에 우선 만족한다.

728x90
728x90
import 'package:flutter/material.dart';

void main() {
  return runApp(MaterialApp(
      title: "Hello World",
      home: Scaffold(
          appBar: AppBar(title: Text('Widget')),
          body: _FirstStatefulWidget())));
}

class _FirstStatefulWidget extends StatefulWidget {
  @override
  State createState() => _FirstStatefulWidgetState();
}

class _FirstStatefulWidgetState extends State<_FirstStatefulWidget> {
  @override
  Widget build(BuildContext context) {
    return Text("statefule widget");
  }
}

stateless 와 다르게 build() 메서드가 없다.

 

statefulWidget을 상속받는 위젯 class -> createState ->

위 클래스를 타입으로하는 State를 상속받는 클래스 -> build 메소드

 

statefulWidget 은 상태를 가진다.

변동부 + 고정부

변동부 =_FirstStatefulWidgetState

고정부 =_FirstStatefulWidget

 

728x90
728x90

연습 겸 코드 기록으로 작성

데이터베이스는 docker 를 이용해 mariadb 컨테이너를 사용하고, 서버로는 springboot , 프론트로는 react를 사용해보기로 했다.

 

1. mariadb - docker

먼저 docker-desktop 이나 docker가 설치 되어있다는 가정하에 진행한다.

먼저 mariadb 이미지를 pull 받아준다.

docker pull mariadb

docker run으로 mariadb 컨테이너를 만들어 줍니다.

docker run -dit --name=mariadb -p 3307:3306 -e MARIADB_ROOT_PASSWORD=root --restart=always mariadb

docker exec 로 root 접속해 유저생성, 데이터베이스 생성, 권한을 부여해 줍니다.

docker exec -it mariadb mysql -u root -p
password: root
CREATE USER 'hiio'@'%' identified by 'hiio';
CREATE DATABASE HIIO;
GRANT ALL PRIVILEGES ON HIIO.* TO 'hiio'@'%';

connect 연결테스트를 해보기 위해서 dbeaver로 접속해 봅니다.

 

 

2. spring boot

VScode를 사용합니다.

JDK 는 11버전을 사용합니다.

 

vscode에 java 와 spring boot Extention을 설치 해주고 F1을 눌러 spring boot initialize 를 gradle로 만들어 줍니다.

버전은 2.7.8 를 사용해 줬습니다.

 

언어는 JAVA로 선택하고, 패키지 명을 정해줍니다.

패키지 타입은 JAR로 선택해 줬습니다.

 

JAVA 버전은 11로 선택해 주고 

초기 Dependency 는 Lombok , Devtools, web 을선택해 줬습니다.

디렉토리를 선택해면 그 하위에 파일들이 생기게 됩니다.

 

 

PracApplication 을 실행해 봅니다.

 

잘 실행이 되네요.

 

3. create-react-app

node 를 설치한 상태에서 npx를 사용해 create-react-app 으로 리액트를 설치해 줍니다.

 

설치가 완료되고 나서 front 디렉토리로 이동후에 npm run start 명렁어로 실행해 봅니다.

 

완료! 

 

728x90
728x90

[AWS] 계정 만들기


계정 생성!

728x90

'project > aws' 카테고리의 다른 글

[AWS] 2024-05-24 EC2  (0) 2024.05.24
[AWS] 예산 설정  (0) 2024.05.24
[AWS] TIL 2024-05-22  (0) 2024.05.22
728x90

[Project][SVG] Text를 그려보자!


SVG 에는 text 태그를 이용해 원하는 text를 표현할 수 있습니다.

x,y 속성을 통해서 위치를 정하고, textAnchor 나 alignmentBaseline 등으로 text를 좌표기준 정렬 시킬수 있습니다.

https://developer.mozilla.org/en-US/docs/Web/SVG/Element/text

전체 코드


// src\project\s\svg\components\text.js

// modules
import React, { useRef, forwardRef, useEffect, useState } from "react";

const Text = forwardRef(({ x, y, children, config = {} }, ref) => {
  const textRef = ref || useRef();
  const [options, setOptions] = useState({
    textAnchor: "middle",
    alignmentBaseline: "middle",
  });
  useEffect(() => {
    setOptions((p) => ({ ...p, ...config }));
  }, [config]);
  return (
    <text x={x} y={y} {...options} ref={textRef}>
      {children}
    </text>
  );
});

export default Text;

Arc를 그릴때와 마찬가지로 forwardRef 를 통해 부모 컴포넌트에서 tex 컴포넌트를 접근할 수 있도록합니다.

Arc 그리지 → https://twentytwentyone.tistory.com/122

이번에는 props로 넘어온 options을 text에 spread operator로 넘겨주어 따로 props 값을 지정해주는 수고를 덜었습니다.

데모는 아래의 링크에서 확인할 수 있습니다.

http://localhost:8080/work/s/svg

728x90

'project > svg' 카테고리의 다른 글

[Project][SVG] Arc 를 그려보자!  (0) 2022.07.06
728x90

[Project][SVG] Arc 를 그려보자!


SVG 로 Arc를 그리기 위해서는 path를 사용해야합니다.

path의 d 속성에는 여러개의 명령어가 있는데, 그중 M 과 A 를 이용해 그려보는 react 용 Arc Component를 만들어 봅니다.

https://developer.mozilla.org/ko/docs/Web/SVG/Tutorial/Paths

 

A 명령어


원호를 그릴수 있는 명령어인 A는

A rx ry x축-회전각 큰-호-플래그 쓸기-방향-플래그 x y 로 이루어져있습니다.

rx 는 x축 반지름

ry 는 y축 반지름 입니다.

큰-호-플래그 는 180도를 기준으로 중심각을 결정합니다.

 

M 명령어


M 명령어는 Move To 호를 그릴 시작 좌표를 지정해줍니다.

 

Arc Components


Arc component는 A명령어의 파라미터를 채우기위해 2가지의 유틸성 함수를 사용하고,

parameter로

className = "", id = "", cx, cy, r, startDeg, endDeg, fill = "none", stroke = "#446688", strokeWidth = "2",

를 받습니다.

중심 좌표 cx,cy와 반지름 r, 시작각도 startDeg,끝 각도 endDeg, 원호를 꾸며줄 속성들입니다.

 

get Points


먼저 시작 좌표와 끝좌표를 구해야합니다.

구하기 위해서는 각도를 호도로 변환하여 한 좌표와 반지름을 알고있으므로 cos,sin을 이용해 다른 2좌표를 구합니다.

 

const getPoint=(cx, cy, r, deg)=> {   const rad = ((deg - 90) * Math.PI) / 180.0;    return {     x: cx + r * Math.cos(rad),     y: cy + r * Math.sin(rad),   }; }

 

get Attribute d


이렇게 구한 좌표를 가지고, path 태그의 d속성에 넣어줄 명령어 문자열을 만들어 주어야합니다.

const getAttrD=(cx, cy, r, startDeg, endDeg)=> {   const startPos = getPoint(cx, cy, r, startDeg);   const endPos = getPoint(cx, cy, r, endDeg);   const largeArcFlag = endDeg - startDeg > 180 ? 1 : 0;   return `M${startPos.x},${startPos.y}A${r},${r},0,${largeArcFlag},1,${endPos.x},${endPos.y}`; }

getPoint를 이용해 구한 start Point 와 endPoint를 각각 M과 A에 넣어주고, 나서

largetArcFlag를 구해줍니다.

시작각도와 끝각도의 차이가 180도가 넘어가면 1을 아니면 0을 지정해줍니다.

 

전체 코드


 

// src\project\s\svg\components\arc.js
// modules
import React, { useRef, useEffect, useState, forwardRef } from "react";

const Arc = forwardRef(
  (
    {
      className = "",
      id = "",
      cx,
      cy,
      r,
      startDeg,
      endDeg,
      fill = "none",
      stroke = "#446688",
      strokeWidth = "2",
    },
    ref
  ) => {
    const pathRef = ref || useRef();
    const [d, setD] = useState("");
    useEffect(() => {
      setD(getAttrD(cx, cy, r, startDeg, endDeg));
    }, [cx, cy, r, startDeg, endDeg]);
    return (
      <path
        className={className}
        id={id}
        ref={pathRef}
        d={d}
        fill={fill}
        stroke={stroke}
        strokeWidth={strokeWidth}
      ></path>
    );
  }
);

export default Arc;

const getPoint = (cx, cy, r, deg) => {
  const rad = ((deg - 90) * Math.PI) / 180.0;

  return {
    x: cx + r * Math.cos(rad),
    y: cy + r * Math.sin(rad),
  };
};

const getAttrD = (cx, cy, r, startDeg, endDeg) => {
  const startPos = getPoint(cx, cy, r, startDeg);
  const endPos = getPoint(cx, cy, r, endDeg);
  const largeArcFlag = endDeg - startDeg > 180 ? 1 : 0;
  return `M${startPos.x},${startPos.y}A${r},${r},0,${largeArcFlag},1,${endPos.x},${endPos.y}`;
};

 

추가적으로 forwardRef 를 통해 부모 컴포넌트에서 arc 컴포넌트를 접근할 수 있도록합니다.

 

데모는 아래의 링크에서 확인할 수 있습니다.

http://localhost:8080/work/s/svg

728x90

'project > svg' 카테고리의 다른 글

[Project][SVG] Text를 그려보자!  (0) 2022.07.07

+ Recent posts