4월 14일 (금) - []
◆ 이전 개념 정리
외부에서의 데이터 접속
- 프로토콜, IP, Port 필요
웹서버의 HTML 데이터 ( Image 데이터 포함 )
1. HTML : 크롤링, 스크래핑 → 가공 필요
- 공개되어 있지만 공식 제공자료는 아님
▶ String, StringBuffer, StringBuilder
▶ Regular Expression ( POSIX )
▶ Library ( API ) - JSoup
2. OpenAPI : 공식 제공 ( 회원가입 - API KEY )
▶ Text ( CSV / XML / JSON )
▷ CSV : Comma - Separated
▷ XML : 태그를 이용해 공유 가능한 방식으로 데이터를 전송
▷ JSON : JavaScript Object Notation
▶ Library ( API )
▶ JSON 으로 작성된 소스를 분석하고 양식에 맞게 배치해주는 사이트 : ( https://jsonlint.com )
The JSON Validator
JSONLint is the free online validator and json formatter tool for JSON, a lightweight data-interchange format. You can format json, validate json, with a quick and easy copy+paste.
jsonlint.com
Q. 영화진흥위원회 오픈 API ( www.kobis.or.kr ) → 주간/주말 박스오피스 에서 XML 데이터를 가져온 뒤, 최신 날짜의 데이터로 수정한다. 그 후, 영화의 랭킹과 영화 이름의 데이터를 추출하는 코드를 작성
- Key 1. 초기 데이터는 1줄의 데이터로 이루어져 있다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
public class ParsingEx01 {
public static void main(String[] args) {
// Parsing - 문서 분석
BufferedReader br = null;
try {
URLConnection conn = new URL( "https://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchWeeklyBoxOfficeList.xml?key=f5eef3421c602c6cb7ea224104795888&targetDt=20230409" ).openConnection();
br = new BufferedReader( new InputStreamReader( conn.getInputStream() ) );
String line = br.readLine();
line = line.replaceAll( "><", ">\n<" );
// 순위, 영화명
String [] lines = line.split ( "\n" );
for ( String data : lines ) {
if ( data.trim().startsWith( "<rank>") ) {
System.out.println( data.trim().replaceAll("<rank>", "")
.replaceAll("</rank>", "" ) );
}
if ( data.trim().startsWith( "<movieNm>") ) {
System.out.println( data.trim().replaceAll("<movieNm>", "")
.replaceAll("</movieNm>", "" ) );
}
}
} catch (MalformedURLException e) {
System.out.println ( "[에러] " + e.getMessage() );
} catch (IOException e) {
System.out.println ( "[에러] " + e.getMessage() );
} finally {
if ( br != null ) try { br.close(); } catch ( IOException e ) {}
}
}
}
Q. 위에서 사용한 한 줄의 데이터를 Jsoup을 이용해 순위 정보만 추출하는 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class ParsingEx02 {
public static void main(String[] args) {
// Parsing - 문서 분석
BufferedReader br = null;
try {
URLConnection conn = new URL( "https://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchWeeklyBoxOfficeList.xml?key=f5eef3421c602c6cb7ea224104795888&targetDt=20230409" ).openConnection();
br = new BufferedReader( new InputStreamReader( conn.getInputStream() ) );
String data = br.readLine();
Document doc = Jsoup.parse( data );
// System.out.println( doc );
Elements rankTags = doc.getElementsByTag( "rank" );
// System.out.println( rankTags );
for( int i=0; i<rankTags.size(); i++ ) {
Element rankTag = rankTags.get(i);
System.out.println( rankTag.text() );
}
} catch (MalformedURLException e) {
System.out.println ( "[에러] " + e.getMessage() );
} catch (IOException e) {
System.out.println ( "[에러] " + e.getMessage() );
} finally {
if ( br != null ) try { br.close(); } catch ( IOException e ) {}
}
}
}
Q. 영화진흥위원회 오픈 API ( www.kobis.or.kr ) → 영화 상세정보에서 XML 데이터를 가져온 뒤,
영화 고유번호, 영화 제목, 배우 목록을 출력하는 코드 작성
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
public class ParsingEx03 {
public static void main(String[] args) {
BufferedReader br = null;
try {
URLConnection conn = new URL( "http://www.kobis.or.kr/kobisopenapi/webservice/rest/movie/searchMovieInfo.xml?key=f5eef3421c602c6cb7ea224104795888&movieCd=20124079" ).openConnection();
br = new BufferedReader( new InputStreamReader( conn.getInputStream() ) );
String data = br.readLine();
Document doc = Jsoup.parse( data );
Elements movieCdTags = doc.getElementsByTag( "movieCd" );
Elements movieNmTags = doc.getElementsByTag( "movieNm" );
Elements actorTags = doc.getElementsByTag( "actor" );
Elements [] tags = { movieCdTags, movieNmTags, actorTags };
for ( Elements tag : tags ) {
for ( int i=0; i<tag.size(); i++ ) {
Element totalTags = tag.get(i);
System.out.println( totalTags.text() );
}
}
} catch (MalformedURLException e) {
System.out.println ( "[에러] " + e.getMessage() );
} catch (IOException e) {
System.out.println ( "[에러] " + e.getMessage() );
} finally {
if ( br != null ) try { br.close(); } catch ( IOException e ) {}
}
}
}
json.org - json simple - README.txt - json simple 1.1.1 download
Q. JSONParser 예제
import org.json.simple.JSONArray;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class JSonEx01 {
public static void main(String[] args) {
// {} / []
String strJson = "[8, 9, 6, 2, 9]";
JSONParser parser = new JSONParser();
try {
JSONArray array = (JSONArray)parser.parse( strJson );
System.out.println( array );
System.out.println( array.size() );
for( int i=0; i<array.size(); i++ ) {
// 정수형 - long
long data = (long)array.get(i);
System.out.println( data );
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Q 예제2
import org.json.simple.JSONArray;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class JSonEx02 {
public static void main(String[] args) {
// {} / []
String strJson = "[ \"8\", \"9\", \"6\", \"2\", \"9\" ]";
JSONParser parser = new JSONParser();
try {
JSONArray array = (JSONArray)parser.parse( strJson );
System.out.println( array );
System.out.println( array.size() );
for( int i=0; i<array.size(); i++ ) {
String data = (String)array.get(i);
System.out.println( data );
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Q. 예제 3
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class JSonEx03 {
public static void main(String[] args) {
// {} / []
String strJson = "{ \"data1\" : \"value1\", \"data2\" : \"value2\" }";
JSONParser parser = new JSONParser();
try {
JSONObject obj = (JSONObject)parser.parse( strJson );
String data1 = (String)obj.get( "data1" );
System.out.println( data1 );
String data2 = (String)obj.get( "data2" );
System.out.println( data2 );
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Q. 예제4
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class JSonEx04 {
public static void main(String[] args) {
// {} / []
String strJson = "{ \"data1\" : [1, 2, 3, 4], \"data2\" : [ \"10\", \"20\", \"30\", \"40\"] }";
JSONParser parser = new JSONParser();
try {
JSONObject obj = (JSONObject)parser.parse( strJson );
JSONArray arr1 = (JSONArray)obj.get( "data1" );
System.out.println( arr1 );
JSONArray arr2 = (JSONArray)obj.get( "data2" );
System.out.println( arr2 );
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Q. 예제 5
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class JSonEx05 {
public static void main(String[] args) {
// {} / []
String strJson = "[ { \"name\" : \"홍길동\", \"city\" : \"서울\" }, { \"name\" : \"박문수\", \"city\" : \"경기\" } ]";
JSONParser parser = new JSONParser();
try {
JSONArray arr = (JSONArray)parser.parse( strJson );
for ( int i=0; i<arr.size(); i++ ) {
JSONObject object = (JSONObject)arr.get(i);
String name = (String)object.get("name");
System.out.println(name);
String city = (String)object.get( "city" );
System.out.println( city );
}
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Q. 영화진흥위원회 오픈 API ( www.kobis.or.kr ) → 주간/주말 박스오피스 에서 JSON 데이터를 가져온 뒤, 최신 날짜의 데이터로 수정한다. 그 후 Json-simple을 이용해서 랭킹, 고유번호, 영화 이름을 출력하는 코드 작성
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class ParsingEx04 {
public static void main(String[] args) {
BufferedReader br = null;
try {
URLConnection conn = new URL( "https://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchWeeklyBoxOfficeList.json?key=f5eef3421c602c6cb7ea224104795888&targetDt=20230409" ).openConnection();
br = new BufferedReader( new InputStreamReader( conn.getInputStream() ) );
String line = br.readLine();
// Json-simple → rank, movieCd, movieNm 정보 가져오기
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject)parser.parse( line );
JSONObject obj1 = (JSONObject)obj.get( "boxOfficeResult" );
JSONArray arr1 = (JSONArray)obj1.get( "weeklyBoxOfficeList" );
for ( int i=0; i<arr1.size(); i++ ) {
JSONObject object = (JSONObject)arr1.get(i);
String rank = (String)object.get("rank");
System.out.print(rank + "\t");
String movieCd = (String)object.get( "movieCd" );
System.out.print( movieCd + "\t");
String movieNm = (String)object.get( "movieNm" );
System.out.println( movieNm );
}
} catch (MalformedURLException e) {
System.out.println ( "[에러] " + e.getMessage() );
} catch (IOException e) {
System.out.println ( "[에러] " + e.getMessage() );
} catch (ParseException e) {
System.out.println ( "[에러] " + e.getMessage() );
} finally {
if ( br != null ) try { br.close(); } catch ( IOException e ) {}
}
}
}
Socket ( ServerSocket / Socket )
1. ServerSocket : 제공자용 소켓
▶ 전송 규약 ( TCP / UDP )
- TCP ( Transmission Control Protocol ) : 전화 ( 확인 / 응답 ), 속도가 느림
- UDP ( User Diagram Protocol ) : 방송 ( 확인하지 않음 )
▶ 포트
Q. 서버 설정 후 명령 프롬프트로 실행
package pack1;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServerEx01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
try {
// 한 개의 포트는 한 개의 프로그램만 사용가능
serverSocket = new ServerSocket(7777);
System.out.println( "서버가 준비되었습니다." );
socket = serverSocket.accept();
System.out.println( "클라이언트가 연결되었습니다." );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if ( socket != null ) try { socket.close(); } catch ( IOException e ) {}
if ( serverSocket != null ) try { serverSocket.close(); } catch ( IOException e ) {}
}
}
}
- 명령 프롬프트로 실행중인 상태에서 이클립스에서도 실행하게 되면 아래 에러 메시지가 발생한다.
- 포트 하나 당 한 개의 프로그램만 사용 가능하다.
Q. 클라이언트 설정 후 이클립스로 실행
package pack1;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClientEx01 {
public static void main(String[] args) {
Socket socket = null;
try {
System.out.println( "서버와 연결을 시작합니다." ) ;
socket = new Socket( "localhost", 7777 );
System.out.println( "서버와 연결되었습니다." );
} catch (UnknownHostException e) {
System.out.println( "[에러] " + e.getMessage() );
} catch (IOException e) {
System.out.println( "[에러] " + e.getMessage() );
} finally {
if ( socket != null ) try { socket.close(); } catch ( IOException e ) {}
}
}
}
- 서버쪽 명령 프롬프트에서도 연결된 것을 확인할 수 있다.
Q. 메시지 주고받기
1. TCPServerEx01 클래스
package pack2;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServerEx01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
BufferedWriter bw = null;
try {
// 한 개의 포트는 한 개의 프로그램만 사용가능
serverSocket = new ServerSocket(7777);
System.out.println( "서버가 준비되었습니다." );
socket = serverSocket.accept();
System.out.println( "클라이언트가 연결되었습니다." );
// 다국어 처리
bw = new BufferedWriter( new OutputStreamWriter ( socket.getOutputStream() ) ) ;
bw.write( "Hello Client" + System.lineSeparator() );
System.out.println( "전송이 완료되었습니다." );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if ( bw != null ) try { bw.close(); } catch ( IOException e ) {}
if ( socket != null ) try { socket.close(); } catch ( IOException e ) {}
if ( serverSocket != null ) try { serverSocket.close(); } catch ( IOException e ) {}
}
}
}
2. TCPClientEx01 클래스
package pack2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClientEx01 {
public static void main(String[] args) {
Socket socket = null;
BufferedReader br = null;
try {
System.out.println( "서버와 연결을 시작합니다." ) ;
socket = new Socket( "localhost", 7777 );
System.out.println( "서버와 연결되었습니다." );
br = new BufferedReader( new InputStreamReader( socket.getInputStream() ) );
System.out.println( "메시지 : " + br.readLine() );
} catch (UnknownHostException e) {
System.out.println( "[에러] " + e.getMessage() );
} catch (IOException e) {
System.out.println( "[에러] " + e.getMessage() );
} finally {
if ( br != null ) try { br.close(); } catch ( IOException e ) {}
if ( socket != null ) try { socket.close(); } catch ( IOException e ) {}
}
}
}
3. TCPServerEx01 (명령 프롬프트) 실행 후 TCPClientEx01 (이클립스) 실행
Q. 이번엔 서버에서 메시지를 전달받는 프로그램 ( 다국어 처리 까지 : 한글 전송 )
1. TCPServerEx01 Class
package pack3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServerEx01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
BufferedReader br = null;
try {
// 한 개의 포트는 한 개의 프로그램만 사용가능
serverSocket = new ServerSocket(7777);
System.out.println( "서버가 준비되었습니다." );
socket = serverSocket.accept();
System.out.println( "클라이언트가 연결되었습니다." );
br = new BufferedReader( new InputStreamReader( socket.getInputStream(), "utf-8" ) );
System.out.println( "메시지 : " + br.readLine() );
System.out.println( "수신 완료됨" );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if ( br != null ) try { br.close(); } catch ( IOException e ) {}
if ( socket != null ) try { socket.close(); } catch ( IOException e ) {}
if ( serverSocket != null ) try { serverSocket.close(); } catch ( IOException e ) {}
}
}
}
2. TCPClientEx01 클래스
package pack3;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClientEx01 {
public static void main(String[] args) {
Socket socket = null;
BufferedWriter bw = null;
try {
System.out.println( "서버와 연결을 시작합니다." ) ;
socket = new Socket( "localhost", 7777 );
System.out.println( "서버와 연결되었습니다." );
bw = new BufferedWriter( new OutputStreamWriter ( socket.getOutputStream(), "utf-8" ) ) ;
bw.write( "안녕 서버" + System.lineSeparator() );
} catch (UnknownHostException e) {
System.out.println( "[에러] " + e.getMessage() );
} catch (IOException e) {
System.out.println( "[에러] " + e.getMessage() );
} finally {
if ( bw != null ) try { bw.close(); } catch ( IOException e ) {}
if ( socket != null ) try { socket.close(); } catch ( IOException e ) {}
}
}
}
3. TCPServerEx01 (명령 프롬프트) 실행 후 TCPClientEx01 (이클립스) 실행
Q. 위 프로그램에서 여러 줄을 보내는 프로그램으로 변경
1. TCPServerEx01 Class
package pack3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServerEx01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
BufferedReader br = null;
try {
// 한 개의 포트는 한 개의 프로그램만 사용가능
serverSocket = new ServerSocket(7777);
System.out.println( "서버가 준비되었습니다." );
socket = serverSocket.accept();
System.out.println( "클라이언트가 연결되었습니다." );
br = new BufferedReader( new InputStreamReader( socket.getInputStream(), "utf-8" ) );
String [] arrMsg = br.readLine().split( ":" );
for ( String msg : arrMsg ) {
System.out.println( msg );
}
System.out.println( "수신 완료됨" );
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if ( br != null ) try { br.close(); } catch ( IOException e ) {}
if ( socket != null ) try { socket.close(); } catch ( IOException e ) {}
if ( serverSocket != null ) try { serverSocket.close(); } catch ( IOException e ) {}
}
}
}
2. TCPClientEx01 클래스
package pack3;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClientEx01 {
public static void main(String[] args) {
Socket socket = null;
BufferedWriter bw = null;
try {
System.out.println( "서버와 연결을 시작합니다." ) ;
socket = new Socket( "localhost", 7777 );
System.out.println( "서버와 연결되었습니다." );
bw = new BufferedWriter( new OutputStreamWriter ( socket.getOutputStream(), "utf-8" ) ) ;
bw.write( "안녕 서버 1:안녕 서버 2:안녕 서버 3" + System.lineSeparator() );
} catch (UnknownHostException e) {
System.out.println( "[에러] " + e.getMessage() );
} catch (IOException e) {
System.out.println( "[에러] " + e.getMessage() );
} finally {
if ( bw != null ) try { bw.close(); } catch ( IOException e ) {}
if ( socket != null ) try { socket.close(); } catch ( IOException e ) {}
}
}
}
Q. 반환 예제 ( Echo ) - 스트림 교차 연결
1. TCPServerEx01 클래스
package pack4;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServerEx01 {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
BufferedReader br = null;
BufferedWriter bw = null;
try {
serverSocket = new ServerSocket(7777);
System.out.println( "서버가 준비되었습니다." );
socket = serverSocket.accept();
System.out.println( "클라이언트가 연결되었습니다." );
br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"utf-8"));
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"utf-8"));
String msg = br.readLine();
System.out.println( "메시지 : " + msg );
bw.write( msg + System.lineSeparator() );
// 전송 완료
bw.flush();
System.out.println( "전송이 완료되었습니다." );
} catch (IOException e) {
System.out.println( "[에러] " + e.getMessage() );
} finally {
if ( br != null ) try { br.close(); } catch ( IOException e ) {}
if ( bw != null ) try { bw.close(); } catch ( IOException e ) {}
if ( socket != null ) try { socket.close(); } catch ( IOException e ) {}
if ( serverSocket != null ) try { serverSocket.close(); } catch (IOException e) {}
}
}
}
2. TCPClientEx01 클래스
package pack4;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class TCPClientEx01 {
public static void main(String[] args) {
Socket socket = null;
BufferedWriter bw = null;
BufferedReader br = null;
try {
System.out.println( "서버와 연결을 시작합니다." ) ;
socket = new Socket( "localhost", 7777 );
System.out.println( "서버와 연결되었습니다." );
bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"utf-8"));
br = new BufferedReader(new InputStreamReader(socket.getInputStream(),"utf-8"));
bw.write( "Hello Echo Server" + System.lineSeparator() );
bw.flush();
System.out.println( "전송이 완료되었습니다." );
String msg = br.readLine();
System.out.println( "에코 메시지 : " + msg );
} catch (UnknownHostException e) {
System.out.println( "[에러] " + e.getMessage() );
} catch (IOException e) {
System.out.println( "[에러] " + e.getMessage() );
} finally {
if ( bw != null ) try { bw.close(); } catch ( IOException e ) {}
if ( br != null ) try { br.close(); } catch ( IOException e ) {}
if ( socket != null ) try { socket.close(); } catch ( IOException e ) {}
}
}
}
Q.
1. 클라이언트에서 구구단의 단수를 입력하고,
2. 서버에서 구구단의 문자열을 생성해서 클라이언트로 전송
3. 클라이언트에서 구구단 출력