JUnit의 개요

- Java에서 독립된 단위테스트(Unit Test)를 지원해주는 프레임워크이다.

- Desgin 패턴과 Eclipse IDE를 개발한 Erich Gamma가 제작한 프레임워크다.

- 단정(assert) method로 테스트 케이스의 수행 결과를 판별한다.

- jUnit4부터는 테스트를 지원하는 어노테이션을 제공한다. (@Test, @Before, @After)

- 각 @Test 메서드가 호출할 때 마다 새로운 인스턴스를 생성하여 독립적인 테스트가 이루어지도록 한다.




단위테스트(Unit Test)란?

- 소스코드의 특정 모듈이 의도된 대로 정확히 작동하는지 검증하는 절차, 즉 모든 함수와 메소드에 대한 테스트 케이스(Test case)를 작성하는 절차를 말한다.

- JUnit은 보이지 않고 숨겨진 단위 테스트를 끌어내어 정형화시켜 단위테스트를 쉽게 해주는 테스트 지원 프레임워크다




JUnit Annotation

@Test

- @Test가 선언된 메서드는 테스트를 수행하는 메서드가 된다.

- JUnit은 각각의 테스트가 서로 영향을 주지 않고 독립적으로 실행됨을 원치으로 하므로 @Test 마다 객체를 생성한다.



@Ignore

- @Ignore가 선언된 메서드는 테스트를 실행하지 않게 한다.



@Before

- @Before가 선언된 메서드는 @Test 메서드가 실행되기 전에 반드시 실행되어 진다.

- @Test 메소드에서 공통으로 사용하는 코드를 @Before 메소드에 선언하여 사용하면 된다.



@After

- @After가 선언된 메서드는 @Test 메소드가 실행된 후 실행된다.



@BeforeClass

- @BeforeClass 어노테이션은 @Test 메소드보다 먼저 한번만 수행되어야 할 경우에 사용하면 된다.



@AfterClass

- @ AfterClass 어노테이션은 @Test 메소드보다 나중에 한번만 수행되어야 할 경우에 사용하면 된다.





JUint Method

method name 

description 

 assertEquals(a, b)

객체 a와 b의 값이 일치함을 확인한다. 

 assertArrayEquals(a, b)

배열 a와 b의 값이 일치함을 확인한다. 

 assertSame(a, b) 

객체 a와 b가 같은 객체임을 확인한다.

assertEquals 메서드는 두 객체의 값이 같은지 확인하고 assertSame 메서드는 두 객체의 레퍼런스가 동일한가를 확인한다. 

 assertTrue(a) 

조건 A가 참인가를 확인한다.

 assertNotNull(a) 

 객체 A가 null이 아님을 확인한다.


그 외 다양한 테스트용 메소드를 제공한다.


'JAVA > SPRING FRAMEWORK' 카테고리의 다른 글

[Spring] JUnit의 어노테이션과 메소드  (0) 2018.09.10
[Spring] IoC와 DI  (0) 2018.09.10
Posted by 루우지

IoC (Inversion of Control) 와 DI(Dependency Injection)

- "제어의 역전" 즉 인스턴스 생성부터 소멸까지의 인스턴스 생명주기 관리를 개발자가 아닌 컨테이너가 대신 해준다 라는 뜻이다.

- 컨테이너 역할을 해주는 프레임워크에게 제어하는 권한을 넘겨서 개발자의 코드가 신경 써야 할것을 줄이는 전략이다.

- IoC 컨테이너는 객체의 생성을 책임지고, 의존성을 관리한다.

- POJO의 생성, 초기화 서비스, 소멸에 대한 권한을 가진다.

- 개발자가들이 직접 POJO를 생성 할 수 있지만 컨테이너에게 맡긴다.



DL (Dependency Lookup) : 의존성 검색

 - 저장소에저장되어 있는 Bean에 접근하기 위해 컨테이너가 제공하는 API를 이용하여 Bean을 Lookup하는 것


DI (Dependency Injection) : 의존성 주입

 - 각 클래스간의 의존관계를 빈 설정정보르 바탕으로 컨테이너가 자동으로 연결 해주는 것]


DL사용시 컨테이너에 종속성이 증가하여 주로 DI를 사용한다.


DI의 유형 

1) Setter Injection : Setter 메서드를 이용한 의존성 삽입

 - 의존성을 입력 받는 setter 메서드를 마들고 이를 통해 의존성을 주입한다.

2) Constructor Injection

 - 필요한 의존성을 포함하는 클래스의 생성자를 만들고 이를 통해 의존성을 주입한다.

3) Method Injection

 - 의존성을 입력 받는 일반 메서드를 만들고 이를 통해 의존성을 주입한다.








다형성 Polymorphism = Poly(다양한) + Morphism(변형, 변신)




객체를생성할때 다형성에 의거해서 아래와 같이 생성을 하면



Printer p1 = new StringPrinter();

Printer p2 = new ConsolePrinter();

부모클래스타입  변수 = new 자식 클래스의타입();



위와 같은 형식으로 으로 코드를 작성하면 아래와 같은 뜻을 내포한다.

-> StringPrinter 클래스는 Printer 타입이다.

-> ConsolePrinter 클래스는 Printer 타입이다. 


- 이게 바로 java에서 말하는 다형성이다.

- 타입은 Printer 타입이지만 다양한 StringPrinter, ConsolePrinter 변형이 가능하다.

- 구현체는 언제든지 바뀔수 있기 때문에 인터페이스만 바라보게끔 하는 방식 








Setter Injection의 <property> tag

- Setter method를 통해 의존관계가 있는 Bean을 주입하려면 <property> tag의 ref 속성을 사용 할 수있다.

- Setter method를 통해 Bean의 레퍼런스가 아니라 단순 값을 주입하려고 할 때는 <property>tag의 value 속성을 사용한다.

ref -> Bean id를 이용하여 주입할 Bean을 찾는다.

value -> 단순 값 또는 Bean이 아닌 객체를 주입할 때 사용한다.

public class Hello {
	String name; 
	Printer printer;

	public Hello() {};

	public void setName(String name) {
		this.name = name;
	}

	public void setPrinter(Printer printer) {
		this.printer = printer;
	}
}


위의 소스를 xml로 빈설정을 해주면 아래와 같다.


<bean id="Hello" class="source.Hello">

<property name="name" values="Spring" />    // setName Method

<property name="printer" ref="printer" />       // setPrinter Method 

</bean>

<bean id="printer" class="source.StringPrinter" />


보기 쉽게 각각의 키워드가 의미하는 바를 소스와 xml에서 찾을 수 있도록 하이라이팅해봤다.








Constructor Injection의 <constructor-arg> tag

- Constructor를 통해 의존관계가 있는 Bean을 주입하려면 <constructor-arg> tag를 사용할 수 있다.

- Constructor 주입방식은 생성장의 파라미터를 이요하기 때문에 한번에 여러개의 객체를 주입할 수 있다.


public class Hello {
	String name;
	Printer printer;

	public Hello() {};

	public Hello(String name, Printer printer) {
		this.name = name;
		this.printer = printer;
	}
}

1) Constructor-arg index지정하여 파라메터를 넘겨주는 경우

<bean id="hello" class="source.Hello">

<constructor-arg index="0" value="Spring"/>

<constructor-arg index="1" ref="printer" />

</bean>


2) Constructor-arg Paramater name 지정하여 넘겨주는 경우

<bean id="hello" class="source.Hello">

<constructor-arg name="name" value="Spring"/>

<constructor-arg name="printer" ref="printer" />

</bean>








Collection Type의 값 Injection

- Spring은 List, Set, Map, Properties와 같은 Collection Framework 타입을 XML로 작성해서 프로퍼티에 주입하는 방법을 제공한다.


1) 프로퍼티가 Set과 List일 경우

<bean id="hello" class="source.Hello">

<property name="names">

<list>

<values>Spring</values>

<values>IoC</values>

<values>DI</values>

</list>

</property>

</bean>

- Set으로 설정할경우 list를 set으로 설정하면 된다.


2) Map 타입 : <map>과 <entry> tag를 사용

<bean id="hello" class="source.Hello">

<property name="names">

<list>

<entry key="Kim" values="30"/>

<entry key="Lee" values="35"/>

<entry key="Ahn" values="40"/>

</list>

</property>

</bean>








Spring DI Container의 개념

- Spring DI Container가 관리한는 객체를 빈(Bean)이라고 하고, 이 빈(Bean)들을 관리한다는 의미로 컨테이너를 빈 팩토리라고 부른다.

- 객체를 생성과 객체 사이의 런타임(run-time) 관계를 DI 관점에서 볼 때는 컨테이너를 BeanFactory라고 한다.

- Bean Factory에서 여러 가지 컨테이너 기능을 추가하여 애플리케이션 컨텍스트라고 부른다.








* POJO(Plain Old Java Object)

-> JVM으로만 동작하는 객체를 POJO라한다. 일반 Java Class 객체를 뜻한다.


* Bean 

-> 스프링이 IoC방식으로 관리ㄷ는 객체라는 뜻, 스프링이 직접생성과 제어를 담당하는 객체를 Bean이라고 부른다.


* Bean Factory 

-> 스프링의 IoC를 담당하는 핵심 컨테이너를 가리킨다.

-> Bean을 등록 생성 조회 반환하는 기능을 담당함

-> 보통 BeanFacotry를 바로 사용하지 않고 ApplicationContext를 주로 이용한다.


* ApplicationContext

-> BeanFactory를 확장한 IoC 컨테이너이다.

-> Bean을 등록, 생성, 조회, 반환 관리하는 기능은 BeanFactory와 같다.

-> Spring에서는 ApplicationContext를 BeanFactory보다 더 많이 사용된다.

-> Spring의 각종 부가 서비스를 추가로 제공한다.

-> Spring이 제공하는 ApplicationContext 구현 클래스가 여러가지 종류가 제공된다. 


* Configuration Metadata

-> ApplicationContext 또는 BeanFactory가 IoC를 적용하기위해 사용하는 메타정보를 말한다.

-> 설정 메타정보는 IoC컨테이너에 의해 관리되는 Bean 객체를 생성하고 구성할 때 상용된다.

-> xml로 작성한 bean정보가 metadata에 해당된다.





'JAVA > SPRING FRAMEWORK' 카테고리의 다른 글

[Spring] JUnit의 어노테이션과 메소드  (0) 2018.09.10
[Spring] IoC와 DI  (0) 2018.09.10
Posted by 루우지




증상 : ORA-12638 Credential retrieval failed (신용검색에 실패했습니다) 경고창 출력

원인 : Oracle 설치시 Admin 권한으로 설치하지 않아 발생하는 문제


해결 방법

1. Oracle 설치 경로 찾기

- Oracle Home으로 지정한 경로를 찾아 network\admin 폴더로 이동한다. 

(디폴트로 설치 했을 경우 : C:\app\사용자명\product\11.2.0\client_1\network\admin)




2. sqlnet.ora 파일 수정

- sqlnet.ora 파일을 메모장으로 열어서


SQLNET.AUTHENTICATION_SERVICES= (NTS) <- 이부분을 주석처리한다.



# SQLNET.AUTHENTICATION_SERVICES= (NTS)





이러면 끝!

저장시에 권한문제가 생기면 바탕화면에 임시로 저장 후 해당 파일을 덮어씌우기해서 바꿔치기하면 된다.

'Database > Oracle' 카테고리의 다른 글

[Oracle DB] ORA-12638 신용검색에 실패했습니다 오류  (0) 2018.09.06
Posted by 루우지





















젠킨스란?

- 젠킨스는 Java로제작된 오픈소스 CI(지속적 통합)도구 이다. Jenkins에는 Tomcat 서버가 내장되어 Servlet Container위에 돌아가는 웹서버 이다. 

- SVN, GIT, CVS ... 등과 같은 많은 SCM을 지원한다.

- 쉽게 빌드 결과물을 만들고 테스트하며 배포할수 있는 아주 유용한 도구이다.







젠킨스 다운로드 받기


https://jenkins.io/download/



- 위의 url에 들어가면 다양한 os에서의 젠킨스 설치파일을 제공해준다. 본 게시물에서는 windows os에서의 설치를 다룰 예정이니 windows 설치파일을 다운받는다.




젠킨스 설치하기

- 다운로드 받은 파일을 압출풀고 인스톨러를 실행한다.

- 설치과정은 매우 쉽다. 그냥 NEXT만 눌러주면된다~




- 끝 -



정상 설치가 되었으면 Jenkins 웹서버가 자동으로 구동된다.


http://localhost:8080/


위의 주소로 접속하면 젠킨스의 초기 셋팅을 해줘야한다.









젠킨스는 초기 셋업시 패스워드가 필요하다.

설치된 폴더 C:\Program Files (x86)\Jenkins\secrets 에서


initialAdminPassword파일을 오픈하면 비밀번호가 나오는데 그걸 복사해서 진행해준다.







Jenkins에서 필요한 플러그인을 설치할수 있다.


왼쪽은 추천되는 플러그인 

오른쪽은 사용자가 직접 셀렉할수있는 플러그인 페이지이다.

나는 귀찮으니 왼쪽~




이제 기본적인 셋팅은 끝났다.


http://localhost:8080/


로컬 주소로 재접속을 해보면 



젠킨스가 셋업된 화면을 볼 수있다.





포트번호를 바꿔주고 싶다면?

C:\Program Files (x86)\Jenkins 폴더의 jenkins.xml을 수정해준다.



밑줄친 포트번호를 수정후 저장한뒤 젠키스를 재시작하면 끝~















1


Posted by 루우지


리눅스 os에 익숙하지 않아서 블로그에 정리할겸 올려봅니다.

리눅스에서는 압축파일의 확장자로 tar나 tar.gz파일을 볼 수 있는데요





1. tar 압축

> tar -cvf [파일명.tar]





2. tar 압축 풀기

> tar -xvf [파일명.tar]





3. tar.gz 압축

> gar -zcvf [파일명.tar.gz]





4. tar.gz 압출 풀기

> tar zxvf [파일명.tar.gz]


'Linux OS' 카테고리의 다른 글

[Linux] tar, tar.gz 파일 명령어 (압축하기/압축풀기)  (0) 2018.09.02
Posted by 루우지

1. 메모리 구조


메모리는 크게 4개의 영역으로 나뉜다. 코드 영역, 스택 영역, 힙영역, 데이터 영역 이다.


1) 코드 영역 : 실행 명령어 저장

- 소스코드가 저장되는 영역으로, 실행할 명령어들이 순서대로 쌓인다.

- cpu가 이 영역에서 명령어들을 하나씩 가져다가 처리한다. (큐 구조)



2) 스택 영역 : 개발자가 제일 많이 사용하는 메모리는 스택 메모리 영역이다.  

- 스택이란 모든 원소들의 삽입 삭제를 한쪽 방향에서만 수행하도록 하는 선형 자료 구조이다.

- 이를 후입선출방식 (Last In First Out)이라 한다.

- 스택메모리는 지역변수와 매개변수같은 값들이 저장되는 공간이다.



void Test(int a)
{
    char b = 'A';
    int c = 1;
    double d = 3.14;
}

먼저 메모리에 int a 4바이트가 할당되고, char b 1byte, int c 4byte, double d 8 byte가 순서대로 할당되며 함수가 종료될때에는 거꾸로 메모리에서 제거된다. (d, c, b, a)



3) 힙 영역 : 개발자가 직접 할당

- 힙은 컴퓨터 메모리의 일부가 할당되었다가 회수되는 일들의 반복을 의미

- 합은 컴파일시가 아닌 실행 시 사용자로부터 할당 메모리를 입력 받음

- 생성과 삭제를 개발자가 직접 해줘야하는데, 삭제를 해주지 않으면 메모리 누수현상(메모리 릭)이 생긴다. 



4) 데이터 영역 : 전역 변수, 스태틱수 저장

- 전역 변수와 static변수가 저장되는 메모리이다.

- 프로그램 시작시 모든 전역변수와 static 변수가 데이터 영역에 저장되며, 프로그램이 종료시 메모리에서 소멸된다.






2. 동적 메모리 할당

1) 동적으로 메모리를 할당 하는 이유


일반적으로 변수는 컴파일타임에 할당된다. 

그렇다면 다음의 상황에서는 어떻게 될까?


Q. 전교생이 10명인 학교의 학생 수를 배열로 선언한다면?

A. int student[10];


Q. 학생수가 100명으로 늘어나게 되면?

A. int stduent[100];


학생수가 계속 유동적으로 변하게 된다면?

개발자가 그 상황에 맞게 계속 변수를 할당해줄 수 없다. 학생 수를 고정하지 말고 실행시 결정하자는 개념


int num;
fputs("학생수를 입력하세요 : ",stdout);
scanf("%d", &num);
int student[num];
문제점 
 - scanf는 런타임에 실행되지만 사용자가 값을 입력하는건 런타임이다. 
 - int student[num]은 컴파일타임에 실행된다. 런타임에 입력 받은 변수를 컴파일 타임에 대입하는 형태가 되기 때문에 컴파일 에러가 생긴다. 

 해결 방법

 - 실행 중에 학생 수를 알아야 하는 경우, 동적 메모리 할당 기법을 통해 문제 해결이 가능하다.





2) 메모리 할당 및 해제


malloc()

- 동적 메모리 할당 함수의 원형


void* malloc(size_t size);


- malloc 또는 말록이라고도 읽는다.

- 전달인자size는 바이트 단위로 입력한다.

- 메모리 할당이 되면 메모리의 주소값을 리턴한다.

- 메모리 부족 시 null 포인터 리턴한다.

- 리턴형이 void*인데, 타입이 지정되어 있지 않는 포인터를 리턴 한다.



free()

- 동적 메모리 해제 함수의 원형


void free(void* memblock);


- 메모리 사용후 반드시 해제 해야한다. (메모리 누수현상(메모리 릭)이 발생한다.)

- 전달인자로 메모리를 가리키는 포인터를 대입한다.



#include 
#include 

int main(void)
{
    int num;
    int* student);

    fputs("학생 수 입력 : ",stdout);
    scanf("%d", &num);
    student = (int*)malloc(sizeof((int)*num);

    if(student == null)
    {
        printf("메모리가 부족하가 부족하여 메모리를 할당 할 수 없습니다.\n");
        return 0;
    }

    printf("학당된 메모리의 크기는 %d 입니다. \n", sizeof((int)*num);
    free(student);

    return 0;
}



realloc()

- 실시간 메모리를 할당하여 사용한다 해도 사용중에 메모리 크기를 더 늘려야 하는 경우가 발생할 수 있다.

- malloc 함수로 할당된 메모리를 다시 동적으로 재할당해주는 함수가 realloc이다.




#include 
#include 

int main(void)
{
	int i;
	int *arr = (int*)malloc(sizeof(int) * 5);
	int *rearr; 

	for (i = 0; i < 5; i++)
	{
		arr[i] = i + 1;
	}
	rearr = (int*)realloc(arr, sizeof(int) * 10);
	for (i = 0; i < 10; i++)
	{
		rearr[i] = i + 1;
	}
	for (i = 0; i < 10; i++)
	{
		printf("%d\n", rearr[i]);
	}

	free(rearr);
	return 0;
}


calloc()

- malooc 함수와 똑같은 기능을 갖는다

- 전달인자의 형태와 조금 다른데, 메모리 개수와 자료형의 크기를 대입한다.


int* a = (int*)calloc(elt_count, elt_size);

int* a = (int*)malloc(size * sizeof(int));


#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	int num, i, total = 0;
	int* student;

	fputs("학생 수 입력 : ", stdout);
	scanf("%d", &num);
	student = (int*)calloc(num, sizeof(int));

	if (student == NULL)
	{
		printf("메모리가 부족하가 부족하여 메모리를 할당할 수 없습니다.\n");
		return 0;
	}

	for (i = 0; i < num; i++)
	{
		printf("%d번째 학생의 성적 입력 : ", i + 1);
		scanf("%d", &student[i]);
	}
	for (i = 0; i < num; i++)
	{
		total += student[i];
	}
	printf("총점 : %d 평균 : %d \n", total, total / num);
	free(student);
	return 0;
}



memset()

- 메모리 블록에서 모든 바이트를 특정 값으로 설정 할 때 사용하는 초기화 함수


void* memset(void* dest, int c, size_t count)


#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

int main(void)
{
	int* arr= (int*)malloc(sizeof(int) * 10);
	int i;
	
	printf("=========초기화 하기 전========= ");
	for (i = 0; i < 10; i++)
	{
		printf("%d\n", arr[i]);
	}
	memset(arr, 0, sizeof(int) * 10);
	printf("=========초기화 하기 후-======== ");
	for (i = 0; i < 10; i++)
	{
		printf("%d\n", arr[i]);
	}
	free(arr);
	return 0;
}


>



memcpy()

- 메모리를 복사하는 함수


void* memcpy(void* dest, void* src, size_t count);


#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

int main(void)
{
	int* arr1 = (int*)malloc(sizeof(int) * 5);
	int arr2[5];
	int i;
	
	for (i = 0; i < 5; i++)
	{
		arr1[i] = i + 1;
	}
	memcpy(arr2, arr1, sizeof(int) * 5);
	for (i = 0; i < 5; i++)
	{
		printf("%d\n", arr2[i]);
	}
	free(arr1);
	return 0;
}


memcmp()

- 메모리를 비교하는 함수


void* memcmp(const void* ptr1, const void* ptr2, size_t num);


#include <stdio.h>
#include <string.h>

int main(void)
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[10] = { 1,2,3,4,5 };
	
	if (memcmp(arr1, arr2, sizeof(int) * 5) == 0)
	{
		printf("arr 1 == arr2");
	}
	else
	{
		printf("arr 1 != arr2");
	}
	return 0;
}


Posted by 루우지

[C언어] 열거형 enum

C 2018.08.24 19:56

열거형이란?

- 열거형은 enumeration의 약자로 enum(이넘)이라고 읽는다.

- 데이터들을 열거한 집합이다. 

- 컴파일러는 열거형 멤버들을 정수형 상수로 취급한다.




열거형의 사용법

- 키워드는 enum을 사용하여 정의한다.   

#include 

enum Week
{
	sun = 0,
	mon,
	tue,
	wed,
	thu,
	fri,
	sat
};

int main(void)
{
	int day;
	printf("요일을 입력하세요(1.일, 2.월, 3.화, 4.수, 5.목, 6.금, 7.토) : ");
	scanf("%d", &day);

	switch (day)
	{
	case sun:
		printf("sunday");
	case mon:
		printf("monday");
	case tue:
		printf("tueday");
	case wed:
		printf("weday");
	case thu:
		printf("thuday");
	case fri:
		printf("friday");
	case sat:
		printf("atday");
	default:
		printf("err");
	}
	return 0;
}


- 열거형의 멤버들은 각 요일을 나타낸다.

- 첫번째 멤버 sun을 0으로 설정하면 다음 멤버 mon은 각 1씩 증가한다.

Posted by 루우지

1. 구조체란?

- 하나 이상의 서로 다른 종류의 변수들을 묶어서 새로운 자료형을 정의하는 것이다.



구조체를 사용하는 이유

- 연관된 변수들을 하나로 묶어서 관리함으로써 데이터 관리에 유용하다.

- 데이터의 양이 많아지면 궂체가 유리하다.

- 예를 들어 학생정보 관리 변수를 생성할때 이름, 나이, 성별 등의 정보들은 모두 변수로 선언하여 각각의 변수를 별도로 관리하면 연관성을 알 수가 없다. 



구조체 정의 방법

#include 
struct student
{
	char name[10];
	int age;
	int height;
};	// 구조체 정의

int main(void)
{
	struct student st1;	// 구조체 선언
	struct student st2;
}


- struct 키워드는 구조체라는 자료형을 의미

- student 는 만든 구조체의 이름

- name, age, height는 구조체 멤버 변수

- 구조체는 사용자가 정의한 새로운 자로형이다.



구조체 멤버 접근 방법

- 구조체 변수를 통해 구조체 멤버의 값을 참조해야 한다.

- 멤버에 접근시 . 콤마를 사용하는데, 이를 직접 접근이라 한다.


[구조체 변수명].[구조체 멤버]

ex) st1.name, st1.age, st1.height




2. 공용체란?

- 공용체도 사용자가 정의한 자료형이다

- 구조체와의 차이점은 메모리 공간을 공유한다는 점이다.


struct stTemp
{
	char a;
	int b;
	double c;
}st;


위와 같은 구조체가 있을때 메모리가 차지하는 용량은

a = 1byte, b = 4byte, c = 8byte 로 총 13byte가 메모리에 적재된다.

union unTemp
{
	char a;
	int b;
	double c;
}un;


위의 공용체와 같은 경우는 구조체와는 전혀 다른 메모리 적재방식이 적용된다.

제일 큰 멤버변수 double형 c가 8byte가 메모리에 적재되어 각각의 변수가 1회용으로 8byte 메모리안에 적재된다.

구조체는 멤버변수가 각각의 메모리 공간을 할당받고 있지만 공용체는 같은 메모리공간을 모든 변수가 공유하는 형태이다.


#include 

union unTemp
{
	char a;
	int b;
	double c;
}un;

int main(void)
{
	printf("문자형 a의 주소와 크기 : %x, %d\n", &un.a, sizeof(un.a));
	printf("정수형 b의 주소와 크기 : %x, %d\n", &un.a, sizeof(un.b));
	printf("실수형 c의 주소와 크기 : %x, %d\n", &un.a, sizeof(un.c));

	un.a = 'A';
	printf("문자형 a의 값 : %c\n", un.a);
	un.b = 100;
	printf("정수형 b의 값 : %d\n", un.b);
	un.c = 3.14;
	printf("실수형 c의 값 : %.2f\n", un.c);
	printf("문자형 a의 값 : %c\n", un.a);
	return 0;
}



- 시작 주소는 세 변수가 모두 같다.

- 예제의 마지막줄 a값을 다시 출력 시 쓰레기값이 출력된다. 

- 그 이유는 double형 8byte에 저장된 값은 3.14인데 그중 1byte의 값만 읽어와 출력하는것이니 쓰레기값이 출력된다.


공용체를 사용하는 이유

- 메모리 절약을 위해서

- 구조체는 각 가정의 화정실, 공용체는 공원의 공중 화장실이라 생각하면 된다. 


공용체 사용 시 유의 사항

- 공용체 멤버는 동시에 사용하게 되면 데이터가 별질될 우려가 있으므로 따로 따로 사용해야한다.




Posted by 루우지


void CAVI_PROJECTDlg::OnBnClickedBtnFind()
{ 
	BROWSEINFO BrInfo;
	TCHAR szBuffer[512];                                      // 경로저장 버퍼 

	::ZeroMemory(&BrInfo,sizeof(BROWSEINFO));
	::ZeroMemory(szBuffer, 512); 

	BrInfo.hwndOwner = GetSafeHwnd(); 
	BrInfo.lpszTitle = _T("파일이 저장될 폴더를 선택하세요");
	BrInfo.ulFlags = BIF_NEWDIALOGSTYLE | BIF_EDITBOX | BIF_RETURNONLYFSDIRS;
	LPITEMIDLIST pItemIdList = ::SHBrowseForFolder(&BrInfo);
	::SHGetPathFromIDList(pItemIdList, szBuffer);				// 파일경로 읽어오기

	CString str;
	str.Format(_T("%s"),szBuffer);
	AfxMessageBox(str);
}


MFC 버튼컨트롤에 클릭이벤트를 건뒤 해당 함수에 위의 소스를 복붙해서 실행하시면 폴더 찾기 다이얼로그가 생성되는걸 확인 할 수있습니다. 





Posted by 루우지

1. OCI (Oracle Call Interface)

 - Application과 Oracle Database와 상호작용할 수 있도록 오라클에서 지원하는 Low-Level api이다. 일반적으로 C/C++에서 많이 사용된다. 그런데 OCI 프로그래밍은 Low-Level  API를 사용하는것이라 매우 어렵다. 다만 ODBC처럼 Oracle Client를 설치하지 않고 oci 관련된 dll을 같이 배포할때 포함해주면 되기 때문에 사용자가 oracle 을 설치하지 않아도 된다는 이점이 있다. 물론 단점은 위에서 언급했듯이 개발자가 사용하기 쉬운 API는 아니라른점.




2. OCCI (Oracle C++ Call Interface)

 - 약자와 같이 OCCI는 C++에서 오라클DB를 조작할 수 있게금 도와주는 API다. Low-Level로 작성된 OCI를 C++로 랩핑하여 API를 제공해주는데 공식 도큐먼트에서의 OCCI의 장점을 아래와 같이 설명하고 있다.




1) C++과 같은 객체지향 프로그래밍 활용

2) 사용하기 쉽다.

3) JDBC에 익숙한 사람들에게 배우기가 쉽다.









실제로 OCI와 OCCI의 사용 문법은 판이하게 다른다. JDBC에 익숙한 나에게는 OCCI에서 제공해주는 API가 더 친숙하고, 친절하다. 


하지만 OCCI는 단점이 있다..


VS2015에서 사용하면 버그가 생긴다. 

- 정확히는 OCCI가 VS2010 (V100) 까지의 라이브러리 파일을 제공해준다. (dll도 같이)하지만 나는 vs2015를 사용하는데 OCCI(oraocci11d.lib)를 사용할때 getString() 함수를 사용하는데 힙커런트 에러가 뜬다. 이는 내부적으로 2번 메모리를 delete해주는 현상이라고 한다. (정확히는 모름) 무려 저 에러때문에 하루를 다 날려먹었지만 결국 vs2010 으로 갈아타고 작업하는데 성공했다.


해당 에러를 잡으면서 많은 생각을 했다. OCCI를 버리고 OCI로 갈것이냐, ODBC방식으로 갈것이냐, 혹은 JVM을 위에올려서 JDBC로 갈것이냐 등,, 결국 VS2010으로 다운그레이드하여 OCCI를 끝까지 가져가보자라는 방식으로 마음 먹었다.


























Posted by 루우지


티스토리 툴바