AdMob 회원가입 및 프로젝트 생성 

1. admob 가입

https://apps.admob.com/

 

2. 앱 생성
- 앱 추가를 선택

- 안드로이드 선택 

 

3. 광고 단위 추가

 - 저는 배너 광고로 선택하였습니다.

 

프로젝트 적용

1. 프로젝트 수준 build.gradle

allprojects {
    repositories {
        google()
    }
}

 

2. 앱 수준 build.gradle

implementation 'com.google.android.gms:play-services-ads:19.5.0'

 

3. AndroidManifest.xml

앱 > 프로젝트생성 앱 > 앱 설정 앱 ID 하기 입력

하기 value에 가입한 admob에서 프로젝트를 생성한 앱 ID를 입력

<application>
        <!-- Sample AdMob app ID: ca-app-pub-3940256099942544~3347511713 -->
        <meta-data
            android:name="com.google.android.gms.ads.APPLICATION_ID"
            android:value="ca-app-pub-xxxxxxxxxxxxxxxx~yyyyyyyyyy"/>
    </application>

 

4. AdView 추가

노출되는것을 확인하기 위해 하기 adUnitId를 테스트 ID

ca-app-pub-3940256099942544/6300978111 로 진행하도록 합니다.

xml

<com.google.android.gms.ads.AdView
    xmlns:ads="http://schemas.android.com/apk/res-auto"
    android:id="@+id/adView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_gravity="bottom"
    android:layout_marginBottom="5dp"
    ads:adSize="BANNER"
    ads:adUnitId="ca-app-pub-3940256099942544/6300978111">
</com.google.android.gms.ads.AdView>

소스코드

private lateinit var mAdView: AdView
...
fun setupAdMob() {
    MobileAds.initialize(
        this
    ) { }
    mAdView = findViewById(R.id.adView)
    val adRequest = AdRequest.Builder().build()
    mAdView.loadAd(adRequest)
}

 

5. 확인

 - 적용하여 정상적으로 노출하는 것을 확인할 수 있습니다.

 

자세한 내용은 하기 URL에서 확인할 수 있습니다.

https://developers.google.com/admob/android/quick-start?hl=ko

1. props로 하위 콤포넌트에 전달 

useState는 상태 값과 그 값을 갱신하는 함수를 반환합니다.

const [state, setState] = useState(initialState);
setState(newState);

다음은 간단한 useState를 사용하고 props를 통해서 하위 콤퍼넌트로 전달하여 화면에 노출하는 코드입니다.

import React, { useState } from 'react';

const Welcome = (props) => {
  return (
    <>
    <h1>Hello, {props.name}</h1>
    </>
  )
}

const App = () => {
  //상태값
  const [age, setAge] = useState(42);
  return (
    <div className="App">
      <header className="App-header">
        <Welcome name={age}/>
      </header>
    </div>
  )
}

useState를 이용해서 [age, setAge] state 변수 age와 state를 갱신할 수 있는 setAge함수가 만들어지고 

setAge로 값을 설정하면 값이 갱신이되고 컴포넌트를 리 렌더링되게 됩니다.

 

하위 콤포넌트에서 해당 상태값을 참조하기 위해서는 props를 통해서 인자로 넘겨야 해서

상태값이 많거나 하위 component 복잡도가 높아질수록 관리의 어려움이 있습니다.

useContext를 통해서 전달 하도록 개선합니다.

 

2. useContext를 이용하여 global state 

context는 React 컴포넌트 트리 안에서 전역적(global)이라고 볼 수 있는 데이터를 공유할 수 있도록 고안된 방법입니다. 그러한 데이터로는 현재 로그인한 유저, 테마, 선호하는 언어 등이 있습니다.

 

사용방법은 상위 콤포넌트에서 Context를 생성해서 Context.Provider 로 값을 하위로 전달을 하면

하위 컴포넌트에서 필요시 구독하여 값을 사용할 수 있습니다.

 

1. React.createConntext(initialState) 로 Context생성

2. 상위 콤포넌트에서 Context.Provider value로 전달 

3. 하위 콤포넌트에서 useContext를 이용해서 참조 

...
const initialState = {
  index: 0
}
const Reducer = (state, action) => {
  console.log("action : " + action);
  switch (action.type) {
    case 'plus': {
      return { index: state.index + action.value}
    }
    default: {
      return state
    }
  }
}
...


//상위 컴포넌트
export const Context = React.createContext(initialState);
function App() {
  const [state, dispatch] = useReducer(Reducer, initialState)

  return (
    //하위로 value 전달
    <Context.Provider value={{state, dispatch}}>
       <Main />
       <Body />
    </Context.Provider>
  );
}

//하위 콤포넌트 사용하기 
...
//useContext를 이용하여 값을 가져와 사용
const {state, dispatch} = useContext(Context);
...
return (
     {state.index}
)

 

3.전체 소스

프로젝트 생성후 실행 

npx create-react-app my-app
npm start

 

App.js

import React, {useReducer} from 'react';
import Main from "./components/Main";
import Body from "./components/Body";
import './App.css';


const initialState = {
  index: 0
}

const Reducer = (state, action) => {
  console.log("action : " + action);
  switch (action.type) {
    case 'plus': {
      return { index: state.index + action.value}
    }
    default: {
      return state
    }
  }
}

export const Context = React.createContext(initialState);
function App() {
  const [state, dispatch] = useReducer(Reducer, initialState)

  return (
    <Context.Provider value={{state, dispatch}}>
       <Main />
       <Body />
    </Context.Provider>
  );
}

export default App;
import React, {useReducer} from 'react';
import Main from "./components/Main";
import Body from "./components/Body";
import './App.css';


const initialState = {
  index: 0
}

const Reducer = (state, action) => {
  console.log("action : " + action);
  switch (action.type) {
    case 'plus': {
      return { index: state.index + action.value}
    }
    default: {
      return state
    }
  }
}

export const Context = React.createContext(initialState);
function App() {
  const [state, dispatch] = useReducer(Reducer, initialState)

  return (
    <Context.Provider value={{state, dispatch}}>
       <Main />
       <Body />
    </Context.Provider>
  );
}

export default App;

 

Main.js

import React, {useContext, useState, useReducer} from 'react';
import {Context}  from "../App.js";

const Main = () => {
    const {state, dispatch} = useContext(Context);
    return (
      <div className="Main">
      main
      <header className="App-header">
        <p>
        {state.index}
        </p>
        <li
          onClick={()=>{ dispatch({ type: 'plus', value: 1 }) }}
        >
          Plus
        </li>
      </header>
    </div>
    )
}

export default Main;

 

Body.js

import React, {useContext, useState, useReducer} from 'react';
import {Context}  from "../App.js";
const BodyField = (props) => {
  return (
    <>
    <h1>{props.name}</h1>
    </>
  )
}

const Body = () => {
  //값전달
  const {state, dispatch} = useContext(Context);
  return (
    <div className="Body">
      body
      <header className="App-header">
        <BodyField name={state.index}/>
      </header>
    </div>
  )
}

export default Body;

 

결과

App에서 Main과 Body콤포넌트를 가지고 있고 하위 콤포넌트에서 index값을 참조 plus를 클릭시 동시에 갱신이 되는 

간단한 소스를 확인해보았고 Context를 통해서 하위콤포넌트에서 상태값을 공유하는 방법을 사용해 보았습니다.

 

 

 

자세한 내용은 하기 URL에서 확인 할 수 있습니다.

ko.reactjs.org/docs/getting-started.htmlko.reactjs.org/docs/hooks-reference.html#usecontext

 

Hooks API Reference – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

1. 네트워크 드라이버 종류

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f5d0db8f813a        bridge              bridge              local
13d25bc6a925        host                host                local
b1f2996399bf        none                null                local

위와 같이 docker 는 3개의 네트워크를 이용하게 됩니다.

  bridge : 기본 네트워크 드라이버입니다. 드라이버를 지정하지 않은 경우 default bridge를 사용하게됩니다.

  host :  호스트 네트워킹을 직접 사용합니다.

  none : 모든 네트워킹을 비활성화합니다.

 

2. bridge network를 사용하여 테스트해보기

 

하기 두개의 컨테이너를 실행시켜 봅니다

$ docker run -dit --name alpine1 alpine ash
$ docker run -dit --name alpine2 alpine ash

 

실행중인 컨테이너를 확인해 봅니다.

$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
22654255a870        alpine              "ash"               6 seconds ago       Up 5 seconds                            alpine2
55159257b891        alpine              "ash"               15 seconds ago      Up 14 seconds                           alpine1

 

하기 명령으로 기본 네트워크를 지정하지 않았으므로  bridge 네트워크에 연결이 된 것을 확인할 수 있습니다.

$ docker network inspect bridge
...
"Name": "bridge",
...
"IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },
 ...
 "Containers": {
            "22654255a8706b9d3ed0efe8b4c2bdf0d99d036910f1205aec5df262a080feb8": {
                "Name": "alpine2",
                "EndpointID": "122a834f82c6675487efe1277e4e074395812cacf57f9ae2fb233d5ed458e4ab",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            },
            "55159257b891c72e810e02ead5b7fedf755f9d5f22d24297de39edc69f54f5d9": {
                "Name": "alpine1",
                "EndpointID": "01d895b00c6f52fa184d130a4413335f083b788a5c10787c779be38edda46348",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            }
        },

 

서로 연동이 잘되기 위하여  alpine1을 연결해 봅니다.

$ docker attach alpine1

//alpine1 -> alpine2로 연결확인 (ok)
# ping -c 2 172.17.0.3
PING 172.17.0.3 (172.17.0.3): 56 data bytes
64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.249 ms
64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.084 ms

//컨테이너 이름으로 연결확인 (ng)
ping -c 2 alpine2
ping: bad address 'alpine2'

 

 

 

3. 서로 컨네이너명으로 연결해 보기 (사용자 정의 브릿지 네트워크 사용)

docker network create --driver bridge alpine-net

 

하기 명령으로 잘 생성된 것을 확인할 수 있습니다.

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
eb7be8cc8508        alpine-net          bridge              local
f5d0db8f813a        bridge              bridge              local
13d25bc6a925        host                host                local
b1f2996399bf        none                null                local

 

테스트 콘테이너 실행

//두개는 네트워크에 연결하가고 alpinne3은 네트워크 지정없이 기본 네트워크에 연결 
$docker run -dit --name alpine1 --network alpine-net alpine ash
$docker run -dit --name alpine2 --network alpine-net alpine ash
$docker run -dit --name alpine3 alpine ash
$docker run -dit --name alpine4 alpine ash
$ docker container ls
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6058ce3e109e        alpine              "ash"               49 seconds ago      Up 48 seconds                           alpine4
3df2d9c59b55        alpine              "ash"               27 minutes ago      Up 27 minutes                           alpine3
33a086be0054        alpine              "ash"               27 minutes ago      Up 27 minutes                           alpine2
3d88d4a925df        alpine              "ash"               27 minutes ago      Up 27 minutes                           alpine1

 

네트워크 inspect 확인

$docker network inspect bridge
...
"Name": "bridge",
...
"Containers": {
            "3df2d9c59b559d64df58f79d336a5495d1ef01a500a07b8d0b083fd8c15682f9": {
                "Name": "alpine3",
                "EndpointID": "0927f81fa6a69146e3cd75b05932b4d628223f266383d920c513c96943d505a5",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
            "6058ce3e109e88e87161f2b780fc18c7f2df4c884ac27e2aafdd958e90794447": {
                "Name": "alpine4",
                "EndpointID": "47248479369fcaba4c2f3f1535e1a7f47b0c5a0847bdc450618ad300b980491e",
                "MacAddress": "02:42:ac:11:00:03",
                "IPv4Address": "172.17.0.3/16",
                "IPv6Address": ""
            }
        },

...


$docker network inspect alpine-net
...
"Name": "alpine-net",
...
"Containers": {
            "33a086be0054693a5b4500f01264104637a0d3e3c2d89747996d89376754d3fd": {
                "Name": "alpine2",
                "EndpointID": "104deba1e3b9d9391846d8d3ea1dea4b80b7a4fc025aaded62c0d48c97ff5ff5",
                "MacAddress": "02:42:ac:13:00:03",
                "IPv4Address": "172.19.0.3/16",
                "IPv6Address": ""
            },
            "3d88d4a925df434b45f474fd2ff2f81199f738640d013053d0a2a9bdc49d8fa7": {
                "Name": "alpine1",
                "EndpointID": "42d16b7058b6bd136f3d02d4c0c42d61cfe5534d252704dfcd882cf054d01614",
                "MacAddress": "02:42:ac:13:00:02",
                "IPv4Address": "172.19.0.2/16",
                "IPv6Address": ""
            }
        },
...

 

연결 테스트

$ docker container attach alpine1

//alpine2으로 컨테이너 명으로 ping

/ # ping -c 2 alpine2 (ok)

PING alpine2 (172.19.0.3): 56 data bytes

64 bytes from 172.19.0.3: seq=0 ttl=64 time=0.099 ms

64 bytes from 172.19.0.3: seq=1 ttl=64 time=0.088 ms



//alpine3으로 ping

ping -c 2 alpine3 (ng)

ping: bad address 'alpine3'



ping -c 2 172.17.0.2 (ng)

packets transmitted, 0 packets received, 100% packet loss

4. 정리

위 테스트를 그림으로 정리를 다시 하면

 

위 테스트를 통해서

  • 같은 네트워크에 있는 컨테이너간만 통신 가능

  • 사용자가 만든 외부 네트워크를 이용하면 컨테이너 이름으로 연결가능

이러한 이해는 여러 서비스를 연결할때 내부 ip를 매번 확인하면서 할 수 없기 때문에

외부 네트워크를 생성해서 컨테이너 이름으로 연결하는 것을 확인하는 테스트였습니다.

 

 

자세한 내용은 하기 document에서 확인할 수 있습니다.

https://docs.docker.com/network/

 

'DevOps' 카테고리의 다른 글

[Docker] HTTPS Let 's Encrypt 인증서 발급받기  (0) 2020.12.14
[Docker] Dockerfile command  (0) 2020.11.20
[Docker] docker 주요 명령어  (0) 2020.11.20
[nginx] nginx 프록시 설정  (0) 2020.11.17

+ Recent posts