본문 바로가기
Java

4/17 - 데이터 입출력, JSON, 데이터 베이스

by Jiwon_Loopy 2025. 4. 19.
반응형

목차


동시 요청


  • 스레드 풀을 이용하여 동시 요청
package ch19.sec05.axma01;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class EchoServer {
	private static ServerSocket serverSocket = null;
	private static ExecutorService executorService = Executors.newFixedThreadPool(10);

	public static void main(String[] args) {
		System.out.println("------------------------------------------------");
		System.out.println("서버를 종료하려면 q 또는 Q를 입력하고 Enter 키를 입력하세요.");
		System.out.println("------------------------------------------------");

		startServer();

		Scanner scanner = new Scanner(System.in);

		while (true) {
			String key = scanner.nextLine();
			if (key.toLowerCase().equals("q")) {
				break;
			}
		}

		scanner.close();

		stopServer();

	}

	public static void startServer() {
		Thread thread = new Thread() {
			@Override
			public void run() {
				try {
					serverSocket = new ServerSocket(50001);
					System.out.println("[서버] 시작됨");

					while (true) {
						Socket socket = serverSocket.accept();

						executorService.execute(() -> {
							try {
								InetSocketAddress isa = (InetSocketAddress) socket.getRemoteSocketAddress();
								System.out.println("[서버] " + isa.getHostName() + "의 연결 요청을 수락함");

								DataInputStream dis = new DataInputStream(socket.getInputStream());
								String message = dis.readUTF();

								DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
								dos.writeUTF(message);
								dos.flush();
								System.out.println("[서버] 받은 데이터를 다시 보냄: " + message);

								socket.close();
								System.out.println("[서버] " + isa.getHostName() + "의 연결을 끊음\\n");
							} catch (Exception e) {

							}
						});
					}

				} catch (Exception e) {
					System.out.println("[서버] " + e.getMessage());
				}
			}
		};
		thread.start();
	}

	public static void stopServer() {
		try {
			serverSocket.close();
			executorService.shutdownNow();
			System.out.println("[서버] 종료됨 ");
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

}

JSON


  • 네트워크 통신에서 가장 많이 사용되는 데이터 형식
  • 표기법
    • 객체 표기
      • { “속성명” : “속성값” }
    • 배열 표기
      • [항목, 항목]
  • JSON 표기법 관련 클래스
    • JSONObject
      • 객체 표기
    • JSONArray
      • 배열 표기
  • Json 쓰기
package ch19.sec06;

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;

import org.json.JSONArray;
import org.json.JSONObject;

public class CreateJsonExample {
	public static void main(String[] args) throws IOException {
		JSONObject root = new JSONObject();
		
		root.put("id", "winter");
		root.put("name", "한겨울");
		root.put("age", 25);
		root.put("student", true);
		
		JSONObject tel = new JSONObject();
		tel.put("home","02-123-1234");
		tel.put("mobile","010-13-1234");
		root.put("tel",tel);
		
		JSONArray skill = new JSONArray();
		skill.put("java");
		skill.put("C");
		skill.put("C++");
		root.put("skiil",skill);
		
		String json = root.toString();
		
		System.out.println(json);
		
		Writer writer = new FileWriter("D:/Temp/member.json",
				Charset.forName("UTF-8"));
		writer.write(json);
		writer.flush();
		writer.close();
		
	}
}

출력 결과

{"skiil":["java","C","C++"],"student":true,"name":"한겨울","tel":{"mobile":"010-13-1234","home":"02-123-1234"},"id":"winter","age":25}
  • Json 읽기
package ch19.sec06;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.Charset;

import org.json.JSONArray;
import org.json.JSONObject;

public class ParseJsonExample {
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new FileReader("D:/Temp/member.json", Charset.forName("UTF-8")));
		
		String json = br.readLine();
		br.close();
		
		JSONObject root = new JSONObject(json);
		
		System.out.println("id: "+ root.getString("id"));
		System.out.println("name: "+ root.getString("name"));
		System.out.println("age: "+ root.getInt("age"));
		System.out.println("student: "+ root.getBoolean("student"));
		
		JSONObject tel = root.getJSONObject("tel");
		System.out.println("home: " + tel.getString("home"));
		System.out.println("mobile: "+ tel.getString("mobile"));
		
		JSONArray skill = root.getJSONArray("skill");
		System.out.print("skill: ");
		for(int i=0;i<skill.length();i++) {
			System.out.println(skill.get(i) + ", ");
		}
	}
}

출력 결과

id: winter
name: 한겨울
age: 25
student: true
home: 02-123-1234
mobile: 010-13-1234
skill: java, 
C, 
C++, 
  • 네이버 API 검색 예제
package ch19;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

public class ApiExamSearchBlog {

    public static void main(String[] args) {
        String clientId = "..."; //애플리케이션 클라이언트 아이디
        String clientSecret = "..."; //애플리케이션 클라이언트 시크릿

        String text = null;
        try {
            text = URLEncoder.encode("그린스토리", "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("검색어 인코딩 실패",e);
        }

        String apiURL = "<https://openapi.naver.com/v1/search/blog?query=>" + text +"&display=3";    // JSON 결과
        //String apiURL = "<https://openapi.naver.com/v1/search/blog.xml?query=>"+ text; // XML 결과

        Map<string, string=""> requestHeaders = new HashMap<>();
        requestHeaders.put("X-Naver-Client-Id", clientId);
        requestHeaders.put("X-Naver-Client-Secret", clientSecret);
        String responseBody = get(apiURL,requestHeaders);

        System.out.println(responseBody);
    }

    private static String get(String apiUrl, Map<string, string=""> requestHeaders){
        HttpURLConnection con = connect(apiUrl);
        try {
            con.setRequestMethod("GET");
            for(Map.Entry<string, string=""> header :requestHeaders.entrySet()) {
                con.setRequestProperty(header.getKey(), header.getValue());
            }

            int responseCode = con.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) { // 정상 호출
                return readBody(con.getInputStream());
            } else { // 오류 발생
                return readBody(con.getErrorStream());
            }
        } catch (IOException e) {
            throw new RuntimeException("API 요청과 응답 실패", e);
        } finally {
            con.disconnect();
        }
    }

    private static HttpURLConnection connect(String apiUrl){
        try {
            URL url = new URL(apiUrl);
            return (HttpURLConnection)url.openConnection();
        } catch (MalformedURLException e) {
            throw new RuntimeException("API URL이 잘못되었습니다. : " + apiUrl, e);
        } catch (IOException e) {
            throw new RuntimeException("연결이 실패했습니다. : " + apiUrl, e);
        }
    }

    private static String readBody(InputStream body){
        InputStreamReader streamReader = new InputStreamReader(body);

        try (BufferedReader lineReader = new BufferedReader(streamReader)) {
            StringBuilder responseBody = new StringBuilder();

            String line;
            while ((line = lineReader.readLine()) != null) {
                responseBody.append(line + "\\n");
            }

            return responseBody.toString();
        } catch (IOException e) {
            throw new RuntimeException("API 응답을 읽는 데 실패했습니다.", e);
        }
    }
}

출력 결과

{
	"lastBuildDate":"Thu, 17 Apr 2025 12:25:46 +0900",
	"total":5198,
	"start":1,
	"display":3,
	"items":[
		{
			"title":"강화1박2일 여행코스 그린스토리<\\/b>투어와 강화도DMZ투어",
			"link":"https:\\/\\/blog.naver.com\\/blackcatgo\\/223623556308",
			"description":"여행 그린스토리<\\/b>투어 #DMZ투어 소개해드릴게요. 강화구석구석 1박2일 여행 코스 강화도 1박2일 여행은 DMZ와 강화원도심투어로 구성되어있어요 그린스토리<\\/b>투어의 장점은 픽업서비스인데요. 사실 뚜벅이여행인... ",
			"bloggername":"사계절 레일 따라 도시&기차 여행",
			"bloggerlink":"blog.naver.com\\/blackcatgo",
			"postdate":"20241018"
		},
		{
			"title":"[인천] 강화당일치기여행\\/그린스토리<\\/b>투어\\/강화도DMZ투어",
			"link":"https:\\/\\/blog.naver.com\\/y___yl\\/223545681631",
			"description":"그린스토리<\\/b>투어 라는 회사의 상품이었는데 결론부터 말하자면 아주 강추하는 프로그램이다. 아침 8시... 정도 이동하는데 탈북 스토리를 들으며 차창 관람을 하다 보면 금방 강화평화전망대에 도착한다.... ",
			"bloggername":"여기저기 이것저것",
			"bloggerlink":"blog.naver.com\\/y___yl",
			"postdate":"20240812"
		},
		{
			"title":"강화 1박 2일 그린스토리<\\/b>투어와 함께한 강화도 DMZ투어",
			"link":"https:\\/\\/blog.naver.com\\/psy8272\\/223626499355",
			"description":"다녀왔는데 그린스토리<\\/b>투어 강화전문여행사의 "강화 구석구석 1박 2일"이라는 프로그램을 통해 말그대로 강화 구석구석을 1박 2일동안 알차게 강화도 DMZ투어를 하고 왔어요 강화 1박 2일 with 그린스토리<\\/b>투어... ",
			"bloggername":"깐따삐아`s sosohan story~♡",
			"bloggerlink":"blog.naver.com\\/psy8272",
			"postdate":"20241020"
		}
	]
}
</string,></string,></string,>

검색 > 블로그 - Search API

  • 블로그 검색해서 원하는 데이터만 추출해보기 (이름, 링크)

package ch19;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONObject;

public class ApiExamSearchBlog {

    public static void main(String[] args) throws IOException {
        String clientId = "..."; //애플리케이션 클라이언트 아이디
        String clientSecret = "..."; //애플리케이션 클라이언트 시크릿
        System.out.print("검색어를 입력하세요 : ");
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        getSearch(clientId,clientSecret , br.readLine());
    }

	private static void getSearch(String clientId,String clientSecret,String query) {
        String text = null;
        try {
            text = URLEncoder.encode(query, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException("검색어 인코딩 실패",e);
        }

        String apiURL = "<https://openapi.naver.com/v1/search/blog?query=>" + text +"&display=3";    // JSON 결과
        //String apiURL = "<https://openapi.naver.com/v1/search/blog.xml?query=>"+ text; // XML 결과

        Map<string, string=""> requestHeaders = new HashMap<>();
        requestHeaders.put("X-Naver-Client-Id", clientId);
        requestHeaders.put("X-Naver-Client-Secret", clientSecret);
        String responseBody = get(apiURL,requestHeaders);

        //블로그 제목, 링크 출력
        JSONObject obj = new JSONObject(responseBody);
        JSONArray items = obj.getJSONArray("items");
        for(int i=0; i < items.length();i ++) {
        	JSONObject item = (JSONObject) items.get(i);
        	System.out.println("이름: " + item.getString("title") + "\\n" + item.getString("link") + "\\n");
        }
	}

    private static String get(String apiUrl, Map<string, string=""> requestHeaders){
        HttpURLConnection con = connect(apiUrl);
        try {
            con.setRequestMethod("GET");
            for(Map.Entry<string, string=""> header :requestHeaders.entrySet()) {
                con.setRequestProperty(header.getKey(), header.getValue());
            }

            int responseCode = con.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) { // 정상 호출
                return readBody(con.getInputStream());
            } else { // 오류 발생
                return readBody(con.getErrorStream());
            }
        } catch (IOException e) {
            throw new RuntimeException("API 요청과 응답 실패", e);
        } finally {
            con.disconnect();
        }
    }

    private static HttpURLConnection connect(String apiUrl){
        try {
            URL url = new URL(apiUrl);
            return (HttpURLConnection)url.openConnection();
        } catch (MalformedURLException e) {
            throw new RuntimeException("API URL이 잘못되었습니다. : " + apiUrl, e);
        } catch (IOException e) {
            throw new RuntimeException("연결이 실패했습니다. : " + apiUrl, e);
        }
    }

    private static String readBody(InputStream body){
        InputStreamReader streamReader = new InputStreamReader(body);

        try (BufferedReader lineReader = new BufferedReader(streamReader)) {
            StringBuilder responseBody = new StringBuilder();

            String line;
            while ((line = lineReader.readLine()) != null) {
                responseBody.append(line + "\\n");
            }

            return responseBody.toString();
        } catch (IOException e) {
            throw new RuntimeException("API 응답을 읽는 데 실패했습니다.", e);
        }
    }
}

출력 결과

검색어를 입력하세요 : 아이폰
이름: 아이폰 정보이용료 주의할점 기본내용
<https://blog.naver.com/nagune1234/223831133834>

이름: 아이폰 정보이용료 주의할점 제반내용
<https://blog.naver.com/wldus0912/223836260545>

이름: 아이폰 콘텐츠이용료 유의점 및 활용법 핵심정보
<https://blog.naver.com/hakifu/223833833601>
</string,></string,></string,>

메모


728x90
반응형