애드센스에 가입하고 블로그에 광고를 추가했는데, 약어로 되어 있는 광고 용어들이 자꾸만 헷갈렸습니다.

 

아하~ 그렇구나! 이해를 하고 넘어가도 다음에 다시 보면 또 헷갈린하고 할까요?

 

블로그 수익에 시작이 애드센스라면 필수 요소는 아마 용어에 대한 이해일 것입니다.

 

 

그래서 이번에는 간단하지만 자꾸 잊어버리게 되는 온라인 광고 용어에 대해서 정리해 보도록 하겠습니다.

 

 

1. 애드센스 광고용어

 

 

(1) 페이지뷰

사용자가 애드센스 광고가 포함된 글을 조회한 횟수 입니다.

글의 포함된 광고의 수와는 상관없이 글을 1 개 볼때마다 1회로 기록됩니다.

방문자가 블로그에서 3개의 글을 보개 된다면 3회가 추가 될 것이니 방문자의 수와는 다를 수 있습니다.

 

(2) 클릭수

사용자가 광고를 실질적으로 클릭한 횟수 입니다.

확률적으로 페이지뷰의 숫자가 높을 수록 클릭수도 높다고 알려져 있습니다.

(링크 단위에서는 링크 클릭 후에 웹페이지에 표시되는 광고를 클릭한 횟수를 말합니다. )

 

(3) CTR (Click Through Ratio, 페이지 클릭률)

몇 개의 페이지가 노출되었을 때 클릭이 발생하는지를 나타냅니다.

클릭수를 페이지뷰로 나눈 값으로 표시됩니다. (CRT = 클릭수 / 페이지뷰)

예를 들어 페이지뷰 : 100, 클릭수 : 1 => CTR : 1 %

 

(4) CPC (Pay  Per  Click, 클릭당 비용)

사용자가 광고를 클릭하여 웹페이지를 방문할 때 클릭 1회당 발생하는 수익 입니다.

광고당 비용이 다르기 때문에 일반화하기 위해서 총 수익을 발생한 클릭수로 나눈 값으로 표시됩니다.

(CPC = 총 수익 / 클릭수)

예를 들어 1달러 광고 1회 클릭, 2달러 광고 1회 클릭시

총 수익 : 3달러, 클릭수 : 2회 => CPC : 1.5 달러 

 

(5) RPM (Revenue Per Mille, 페이지 RPM)

1000회 노출(페이지뷰)이 발생했을 때 예상되는 수입율입니다.

(RPM = (예상 수입 / 페이지뷰) * 1000 )

예를 들어 페이지뷰 : 25, 예상 수입 : 0.15 달러 => RPM : 6 달러

  

 

 

2. 기타 광고 용어

 

 

(1) CPM (Cost Per Mile)

1000회 노출당 확정 가격으로 월정액제 광고를 의미합니다.

광고를 노출하는 것만으로도 수익을 얻을 수 있습니다.

 

(2) CPA (Cost Per Action)

사용자가 광고를 클릭하여 웹페이지를 방문한 후에 회원가입, 이벤트 참여, 구매 등의 일정한 동작을 할 경우 발생하는 수익입니다. CPM(노출),CPC(클릭) 을 넘어 일정한 동작을 해야만 수익이 발생하기 때문에 가장 높은 광고 금액을 얻을 수 있습니다.

 

Posted by maze1008
,

자바(Java) 에 대해 공부하면서 다음과 같은 말을 많이 들어보았을 것입니다.

 

깊은 복사(deep copy) 와 얕은 복사(shallow copy)

참조 복사(call by reference) 와 값 복사(call by value)

 

값을 다른 곳에 복사하여 사용할 때, 복사가 이루어지는 방법에 따라 동작에 많은 영향을 미치게 됩니다.

지금부터 ArrayList 를 사용하여 두 가지 방법이 어떤 차이점을 가지고 있는지 알아보도록 하겠습니다.

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import java.util.ArrayList;
 
public class CopyTest {
    static ArrayList<String> source = new ArrayList<String>();
    static ArrayList<String> destination = new ArrayList<String>();
    
    public static void initArrayList() {
        if (null != source) {
            source.clear();
            source.add("apple");
            source.add("banana");
            source.add("cherry");
        }
 
        if (null != destination) {
            destination.clear();
        }
    }
    
    public static void printArrayList() {
        System.out.println("====== source result ======");
        for (int i = 0; i < source.size(); i++) {
            System.out.println("source ["+i+"] : " +source.get(i));
        }
 
        System.out.println("====== destination result ======");
        for (int i = 0; i < destination.size(); i++) {
            System.out.println("destination ["+i+"] : " +destination.get(i));
        }
    }
 
    public static void main(String[] args) {
        initArrayList();
 
        // TODO : operation
        
        printArrayList();
    }
}
 
cs

 

 

코드를 간단히 살펴보면,  2 개의 ArrayList 가 선언되어 있고(source, destination)

main() 메소드의 // TODO : operation  위치에서 다음과 같은 2가지 동작을 수행한 후

각각의 ArrayList 가 가지고 있는 값을 모두 출력하게 됩니다. 

1. source 에 있는 내용을 destination 에 복사

2. destination 에 항목을 1개 추가

 

 

동일한 동작을 얕은 복사와 깊은 복사로 적용해 보았습니다.

1. 얕은 복사(shallow copy)      

destination = source;

destination.add("kiwi");

  

<결과>

destination 에만 추가한 kiwi 가 source 에도 추가되어 있음을 확인할 수 있습니다.

shallow copy 는 원본과 복사본 둘 중 한쪽의 수정이 양쪽에 모두 영향을 미치게 됩니다.

 

====== source result ======
source [0] : apple
source [1] : banana
source [2] : cherry
source [3] : kiwi 
====== destination result ======
destination [0] : apple
destination [1] : banana
destination [2] : cherry
destination [3] : kiwi

 

2. 깊은 복사(deep copy)      

destination.addAll(source) ; // 또는 destination =(ArrayList<String>)source.clone();

destination.add("kiwi");

  

<결과>

destination 에만 추가한 kiwi 가 source 에는 존재하지 않음을 확인할 수 있습니다.

deep copy 는 원본과 복사본 둘 중 한쪽의 수정이 다른 한쪽에 영향을 미치지 않습니다.

주석으로 표기한 방법으로도 같은 효과를 얻을 수 있습니다.

 

====== source result ======
source [0] : apple
source [1] : banana
source [2] : cherry
====== destination result ======
destination [0] : apple
destination [1] : banana
destination [2] : cherry
destination [3] : kiwi

 

 

 

그런데 여기서 추가적으로 1가지 더 살펴 보아야 하는 부분이 있습니다.

ArrayList  의 Item 으로 객체가(Object) 선언되어 있다면 깊은 복사는 어떻게 동작하게 될까요?

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import java.util.ArrayList;
 
class Fruit {
    private String name;
    private int count;
 
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getCount() {
        return count;
    }
    public void setCount(int count) {
        this.count = count;
    }
}
 
public class CopyTest {
    static ArrayList<Fruit> source = new ArrayList<Fruit>();
    static ArrayList<Fruit> destination = new ArrayList<Fruit>();
    
    public static void initArrayList() {
        if (null != source) {
            source.clear();
            
            String[] names = new String[] {"apple""banana""cherry"};
            for (int i = 0; i < names.length; i++) {
                Fruit f = new Fruit();
                f.setName(names[i]);
                f.setCount(i + 1);
                source.add(f);
            }
        }
 
        if (null != destination) {
            destination.clear();
        }
    }
    
    public static void printArrayList() {
        System.out.println("====== source result ======");
        for (int i = 0; i < source.size(); i++) {
            System.out.println("source["+i+"] name:"+source.get(i).getName());
            System.out.println("source["+i+"] count:"+source.get(i).getCount());
        }
 
        System.out.println("====== destination result ======");
        for (int i = 0; i < destination.size(); i++) {
            System.out.println("destination["+i+"] name:"+destination.get(i).getName());
            System.out.println("destination["+i+"] count:"+destination.get(i).getCount());
        }
    }
 
    public static void main(String[] args) {
        initArrayList();
        
         // TODO : operation
 
        printArrayList();
    }
}
cs

 

코드를 간단히 살펴보면, name 과 count 를 속성으로 갖고 있는 Fruit 클래스가

2 개의 ArrayList 의(source, destination) Item 으로 선언되어 있습니다.

마찬가지로 main() 메소드의 // TODO : operation  위치에서 다음과 같은 2가지 동작을 수행한 후

각각의 ArrayList 가 가지고 있는 값을 모두 출력하게 됩니다. 

1. source 에 있는 내용을 destination 에 복사

2. destination 에 항목을 1개 추가

 

 

동일한 동작을 얕은 복사와 깊은 복사로 적용해 보았습니다.

1. 얕은 복사(shallow copy)      

destination = source;

Fruit f = new Fruit();

f.setName("kiwi");

f.setCount(4);

destination.add(f);

  

<결과>

destination 에만 추가한 kiwi 가 source 에도 추가되어 있음을 확인할 수 있습니다.

shallow copy 는 원본과 복사본 둘 중 한쪽의 수정이 양쪽에 모두 영향을 미치게 됩니다.

 

====== source result ======
source [0] name : apple
source [0] count : 1
source [1] name : banana
source [1] count : 2
source [2] name : cherry
source [2] count : 3
source [3] name : kiwi
source [3] count : 4
====== destination result ======
destination [0] name : apple
destination [0] count : 1
destination [1] name : banana
destination [1] count : 2
destination [2] name : cherry
destination [2] count : 3
destination [3] name : kiwi
destination [3] count : 4

 

2. 깊은 복사(deep copy)     

destination.addAll(source) ; // 또는 destination =(ArrayList<Fruit>)source.clone();

Fruit f = new Fruit();

f.setName("kiwi");

f.setCount(4);

destination.add(f);

  

<결과>

destination 에만 추가한 kiwi 가 source 에는 존재하지 않음을 확인할 수 있습니다.

deep copy 는 원본과 복사본 둘 중 한쪽의 수정이 다른 한쪽에 영향을 미치지 않습니다.

주석으로 표기한 방법으로도 같은 효과를 얻을 수 있습니다.

 

====== source result ======
source [0] name : apple
source [0] count : 1
source [1] name : banana
source [1] count : 2
source [2] name : cherry
source [2] count : 3
====== destination result ======
destination [0] name : apple
destination [0] count : 1
destination [1] name : banana
destination [1] count : 2
destination [2] name : cherry
destination [2] count : 3
destination [3] name : kiwi
destination [3] count : 4

 

 

이것만으로 정말 제대로 된 Fruit 객체에 대한 깊은 복사가 이루어 진 것일까요?

source 의 apple 객체의 count 를 1 에서 10 으로 값을 바꾼다면 destination 에는 영향이 없을까요?

다시 테스트를 진행해 보도록 하겠습니다.

 

* 객체의 깊은 복사(deep copy)

destination.addAll(source) ; // 또는 destination =(ArrayList<Fruit>)source.clone();

Fruit f = destination.get(0);    // "apple"

f.setCount(10);                    // change : 1 -> 10

  

<결과>

분명히 깊은 복사를 진행했는데도 source 와 destination 의 apple 의 count 가 모두 10으로 변경된 것을 확인할 수 있습니다. 결국 두 ArrayList 의 포함된 Fruit 은 같은 객체라는 의미입니다.

 

====== source result ======
source [0] name : apple
source [0] count : 10
source [1] name : banana
source [1] count : 2
source [2] name : cherry
source [2] count : 3
====== destination result ======
destination [0] name : apple
destination [0] count : 10
destination [1] name : banana
destination [1] count : 2
destination [2] name : cherry
destination [2] count : 3

 

이 문제를 해결하기 위해서는 결국 다음과 같은 방법이 필요합니다.

 

* 객체의 깊은 복사(deep copy)

1. Fruit 클래스의 복사 생성자 추가

public Fruit() { }      // 기본 생성자

public Fruit(Fruit f) { // 복사 생성자

   this.name = f.getName();
   this.count = f.getCount();

 }

 

2. main() 메소드에서 객체에 대한 깊은 복사(deep copy) 수행

for (int i = 0; i < source.size(); i++) {
        destination.add(new Fruit(source.get(i)));
}
Fruit f2 = destination.get(0);    // "apple"
f2.setCount(10);                    // change : 1 -> 10

  

<결과>

원본과 복사본 둘 중 한쪽의 수정이 다른 한쪽에 영향을 미치지 않습니다.

이제서야 완전히 독립된 ArrayList 객체 복사가 완료되었습니다.

 

====== source result ======
source [0] name : apple
source [0] count : 1
source [1] name : banana
source [1] count : 2
source [2] name : cherry
source [2] count : 3
====== destination result ======
destination [0] name : apple
destination [0] count : 10
destination [1] name : banana
destination [1] count : 2
destination [2] name : cherry
destination [2] count : 3

 

Posted by maze1008
,

새로운 모든 언어/플랫폼을 접할 때 개발 환경을 설정하고

 

가장 먼저 하게 되는 작업이 "Hello World 출력하기" 일 것입니다.

 

개발 환경 설정 + "Hello World 출력하기" 를 모두 마쳤다면 그 언어의 대해 50% 이상의 벽을 넘었다는 의미처럼 느껴질 정도로 말입니다.

 

자! 그럼 이제 새로운 프로젝트를 생성해서 Hello World 를 출력해 보도록 하겠습니다.

 

혹시 안드로이드 개발환경이 아직 완료되지 않으셨다면 아래 포스팅을 참고하여 주시기 바랍니다.

안드로이드 개발환경 구축하기

 

 

 

1. 프로젝트 생성하기

 

 

이클립스를 실행합니다.

File 메뉴 > New > Project 를 선택합니다.

 

 

 

새로운 프로젝트를 생성하기 위해 다이얼로그가 나타나는 것을 확인할 수 있습니다.

Android 폴더 > Android Application Project 선택 > Next 버튼을 클릭합니다.

 

 

 

생성하고자 하는 Application / Project / Package Name 을 순서대로 입력하고

Minimum Required SDK(지원하고자 하는 최소 버전), Target SDK(타켓 버전), Complie With(프로젝트 컴파일하여 빌드할 때 사용할 버전)을 순서대로 선택합니다.

 

현재 Hello world 프로젝트를 간단하게 실행하기 위해서는 Application Name 만 입력해 주셔도 됩니다.

Next 버튼을 클릭합니다.

 

 

다음에 나타나는 화면들에서는 Next or Finish 버튼을 클릭하여 프로젝트 생성을 완료합니다.

(프로젝트에 대한 상세한 설정을 위해 필요한 부분이지만 대부분 수정을 하지 않습니다.)

 

 

 

 

 

 

 

다이얼로그가 사라지고 좌측 화면에 Application Name 으로 입력했던 HelloWorld 프로젝트가 생성된 것을 확인할 수 있습니다.

 

 

 

2. 프로젝트 실행하기

 

프로젝트(HelloWorld 어플리케이션) 을 실행하기 위해서 AVD 를 생성 및 실행합니다.

안드로이드 AVD 생성 및 옵션 조정

 

 

 

좌측 화면에서 HelloWorld 프로젝트를 선택하고

상단의 툴바에 있는 시작 버튼 > Run As > Android Application 을 선택합니다.

 

 

 

미리 실행해 놓았던 AVD(에뮬레이터)에 HelloWorld 어플리케이션이 실행되어 화면에 나타납니다.

 

실제 스마트폰에 연결해서 테스트 하고 싶다면 AVD(에뮬레이터) 대신 스마트폰을 PC 에 연결하시면 됩니다.

PC 와 스마트폰 연결하기 (ADB 사용)

 

 

만약 PC 에 스마트폰과 AVD(에뮬레이터) 등이 동시에 연결되어 있다면

어떤 디바이스에서 HelloWorld 어플리케이션을 실행할 것인지 선택하기 위한 다이얼로그가 나타나며 (Android Device Chooser) 그곳에서 원하는 디바이스를 선택하시면 됩니다.

 

Posted by maze1008
,