태그 보관물: C#

C#을 이용한 네이버 오픈 API 연동

들어가는 말

요즈음은 포털 사이트에서 Open API를 제공하여 검색의 결과나 다른 정보를 가져와서 필요에 맞게 구성할 수 있게 되었습니다. Open API를 사용하여 그 결과를 가져오는 방법이 언어에 따라 차이가 있는데 C#을 이용한 네이버 오픈 API 연동 에 관하여 알아보도록 하겠습니다.

연동설정 및 대상

먼저 네이버에 애플리케이션을 등록하여야 하는데 이 과정은 아래의 링크를 참고 하시면 됩니다.

https://developers.naver.com/apps/#/register?defaultScope=search

연동에 필요한 기본적인 설정은 되어 있다고 가정하겠습니다. 서비스 API > 검색에서 여러 영역이 있는데 카페글을 대상으로 진행해 보겠습니다. 웹문서, 블로그 등도 비슷한 방식으로 연동하시면 됩니다.

연동방법

C#에서는 WebRequest 클래스를 이용하여 Open API와 연동합니다. 레퍼런스는 아래의 링크에서 확인하실 수 있습니다.

https://msdn.microsoft.com/ko-kr/library/system.net.webrequest(v=vs.110).aspx

연동 자체는 어렵지 않습니다. 다음과 같은 방식으로 결과를 가져옵니다. GetRequestResult 메소드는 네이버 오픈 API URL, 클라이언트 ID와 secret을 전달받아 그 결과를 string으로 반환합니다.

private string GetRequestResult(string openApiUrl, string clientId, string clientSecret)
{
	var requestResult = String.Empty;

	try
	{
		WebRequest request = null;

		request = WebRequest.Create(openApiUrl);

		request.Headers.Add("X-Naver-Client-Id", clientId);
		request.Headers.Add("X-Naver-Client-Secret", clientSecret);

		Stream dataStream = null;

		var response = request.GetResponse();
		dataStream = response.GetResponseStream();
		var reader = new StreamReader(dataStream);
		requestResult = reader.ReadToEnd();
		reader.Close();
		dataStream.Close();
		response.Close();
	}
	catch (Exception ex)
	{
		logger.Fatal("Exception occurred!");
	}

	return requestResult;
}

13, 14행에 클라이언트 ID와 secret를 지정해 주고 openApiUrl은

https://openapi.naver.com/v1/search/cafearticle.json?query=키워드&display=40

와 같은 형태로 지정합니다. 요청 변수 및 출력결과에 대한 설명은 아래의 링크에서 확인하실 수 있습니다.

https://developers.naver.com/docs/search/cafearticle/

결과 반환형식은 XML 또는 JSON으로 지정할 수 있습니다. 사용하기 편한 형태로 지정하여 사용하면 됩니다. 필자는 JSON 형태로 지정하여 결과값을 받았습니다. 그 값을 JSON Parser(Newtonsoft.Json)를 이용하여 parsing 후 값을 가져왔습니다. 예를 들면 다음과 같습니다.

responseJSON = GetRequestResult(openApiUrl, clientId, clientSecret);

var parseJSON = JObject.Parse(responseJSON);

var queryResultCount = Convert.ToInt32(parseJSON["display"]); //검색된 검색 결과의 개수
var totalResultCount = Convert.ToInt32(parseJSON["total"]); //검색 결과 문서의 총 개수

//개별 검색 결과
var cafeTitle = parseJSON["items"][0]["title"].ToString();
var cafeContent = parseJSON["items"][0]["description"].ToString();
var cafeName = parseJSON["items"][0]["cafename"].ToString();
var cafeUrl = parseJSON["items"][0]["cafeurl"].ToString();

5행은 parsing하여 변수에 대입하는 코드이고 나머지는 몇 가지 요소의 값을 가져오는 코드입니다. 위의 링크의 출력 결과 정보와 함께 보시면 됩니다. 링크의 설명에는 개별 검색 결과의 필드가 item 이라고 되어 있는데 실제 결과를 받아보니 items 로 되어 있었습니다. 원하는 값을 가져올 수 없는 경우 반환값의 필드명이 다른 것이 아닌지 확인할 필요가 있습니다.

이상으로 C#을 이용한 네이버 오픈 API 연동 방법에 대하여 알아보았습니다.

 

BackgroundWorker 클래스 사용

WinForm을 이용한 프로그램을 작업할 때 종종 오랜시간 반복적인 작업을 처리하여야 하는 경우가 있습니다. 진행되는 상태를 표시해 주고 일시 중지 혹은 작업이 마무리 되었을 때 사용자에게 알림 메시지를 보여주는 형식으로 작업을 하게 됩니다. 여기서 문제가 반복문안에 UI 를 갱신하는 코드를 넣으면 의도한 대로 동작하지 않게 됩니다. 특히 버튼 이벤트는 반응을 하지 않게되고 작업이 끝난 후 버튼이 눌려지는 듯한 현상을 보이게 됩니다. 이럴 때 BackgroundWorker 클래스 를 사용하여 작업하면 의도한 대로 버튼 이벤트가 발생되도록 할 수 있습니다. 이 클래스는 .Net 2.0 부터 추가되었고 자세한 설명은 다음의 링크에서 확인할 수 있습니다.

MSDN 설명 보기

사용자가 설정한 키워드 목록을 OpenAPI 를 이용하여 검색 결과를 가져오는 간단한 예제를 구성해 보겠습니다. 먼저 Form 을 아래와 같이 디자인 합니다. 처리되는 키워드와 진행 상황을 표시해 줄 Text, Label 컨트롤을 추가합니다.

폼 디자인

폼 디자인

BackgroundWorker 클래스 변수를 선언합니다. 그리고 폼이 초기화될 때 BackgroundWorker 클래스가 동작할 사항을 정의해 줍니다.

private BackgroundWorker bwWrite;

bwWrite = new BackgroundWorker();
bwWrite.WorkerSupportsCancellation = true;
bwWrite.DoWork += new DoWorkEventHandler(doWrite);
bwWrite.RunWorkerCompleted += new RunWorkerCompletedEventHandler(write_RunWorkerCompleted);

5번째 행에 doWrite 라는 메소드를 실행하도록 설정하고 6번째 행에 작업이 종료되면 write_RunWorkerCompleted 메소드가 실행되도록 설정하였습니다. doWrite 메소드에서는 시간이 오래 걸리는 루프 등의 루틴을 추가하면 됩니다. OpenAPI 를 통하여 검색결과를 가져오는 부분이 될 것입니다. write_RunWorkerCompleted 메소드에서는 doWrite 메소드의 호출이 완료되었을 때 원하는 동작을 하도록 작업하면 됩니다.

각 버튼 이벤트를 다음과 같이 정의합니다.

private void btnStart_Click(object sender, EventArgs e)
{
	btnStart.Enabled = false;
	btnStop.Enabled = true;

	bwWrite.RunWorkerAsync();
}

private void btnStop_Click(object sender, EventArgs e)
{
	bwWrite.CancelAsync();
	btnStart.Enabled = true;
	btnStop.Enabled = false;
}

6번째 행에서 이전에 정의한 대로 doWrite 메소드를 실행하도록 RunWorkerAsync 메소드를 호출합니다. 중지 버튼을 클릭하면 CancelAsync 메소드를 호출하여 취소되도록 합니다. 여기서 유의해야 할 것은 CancelAsync 메소드가 호출되었다고 해서 바로 종료되는 것이 아니라는 것 입니다. doWrite메소드 내에서 다음과 같은 방식으로  취소여부를 판단하여 종료하여야 합니다.

private void doWrite(object sender, DoWorkEventArgs e)
{
.
.
.
	for (var i = keywordIndex; i < keyword.Length; i++)
	{
		if (bwWrite.CancellationPending == true)
		{
			e.Cancel = true;
			return;
		}
		.
		.
		.
	}
}

작업진행 사항을 Text, Label의 속성을 변경시키는 방법으로 doWrite 메소드내에 코드를 작성하면 “자신이 만들어진 스레드가 아닌 스레드에서 액세스되었습니다” 라는 오류가 발생합니다. 메시지 내용대로 별도의 스레드에서 폼에 생성된 컨트롤에 접근하려고 하여 발생되는 오류 입니다. 이럴때는 다음과 같이 Invoke 메소드를 호출하는 방식으로 처리합니다. 이렇게 하면 오류가 발생하지 않고 의도한 대로 진행상황을 Label 컨트롤에 나타낼 수 있습니다.

delegate void delegateSetProgressLabel(string text);

private void setProgressLabel(string text)
{
	if (lblProgressStatus.InvokeRequired)
	{
		var delegateCall = new delegateSetProgressLabel(setProgressLabel);

		this.Invoke(delegateCall, text);
	}
	else
	{
		lblProgressStatus.Text = text;
	}
}

간략하게  BackgroundWorker 클래스 사용 방법에 대하여 알아보았습니다.