네트워크 프로그래밍

"Java Network Programming" 책을 기반으로 URLConnections을 간략히 요약하여 정리했습니다.
URL이 가리키는 리소스에 대한 활성화된 연결(Active Connection)을 나타내는 추상 클래스입니다.
URL 클래스보다 훨씬 구체적인 통신 제어가 가능합니다.
특히, HTTP 서버와의 통신에서 강력합니다.
→ 모든 단계 거칠 필요 없음
1. URL 객체 생성: new URL(" ... ");
2. 연결 객체 확보: url.openConnection()을 호출하여 URLConnection 객체를 얻음 (아직 연결 X)
3. 설정 (Configuration): 타임아웃, 캐시 사용 여부, 요청 방식 등을 설정 (연결 전에 해야함)
4. 헤더 읽기: 서버가 보낸 메타데이터 확인
5. 데이터 읽기: getInputStream()을 통해 본문 내용 읽기
6. 데이터 쓰기: getOutputStream()을 통해 데이터를 보냄 (POST 등의 경우)
7. 종료: 연결 닫음
connect()의 역할: 로컬 컴퓨터와 원격 서버 사이에 실제 물리적인 연결(Socket 등)을 맺음.
URLConnection의 유일한 추상 메서드
초기 상태: openConnection()으로 객체를 막 생성했을 때는
Unconnected(연결 X) 상태
암시적 호출(Implicit Call): 개발자가 connect()를 직접 호출하지 않아도 됨
→ getInputStream(), getContent(), getHeaderField() 등 실제 통신이 필요한 메서드를 호출하면, 자바가 알아서 내부적으로 connect()를 먼저 실행
헤더가 응답을 보낼 때, 실제 데이터(HTML, 이미지 등) 앞에 붙여 보내는 정보들입니다.
Content-Type: 상자 안에 무엇이 들었는지 (예: text/html, image/jpeg)
Content-Length: 내용물의 크기가 얼마나 되는지 (바이트 단위)
Date: 언제 보냈는지
Last-Modified: 언제 마지막으로 수정되었는지
반환값: MIME 타입 (예: "text/html" or "text/html; charset=UTF-8")
중요성: 단순히 "이게 HTML이다" 라는 정보 뿐만 아니라,
어떤 문자 인코딩(Charset)으로 작성되었는지 알려줌
만약 서버가 정보를 안 주면 null 반환
텍스트 파일은 그냥 끝까지(-1 나올 때까지) 읽으면 되지만,
바이너리 파일은 정확한 크기 만큼 읽어내는 것이 중요합니다.
get ContentLength() 메서드: 서버가 보내준 헤더 중 Content-Length 값을 읽어 반환합니다.
네트워크 통신에서 10MB짜리 파일을 요청했다고 해서 10MB가 한 번에 뚝딱 도착하지는 않습니다.
패킷 단위로 쪼개져서 들어오기 때문에, 원하는 크기가 찰 때까지 반복해서 읽어야 합니다.
최신 환경에서는 2GB 이상의 파일이 흔하므로, int를 반환하는 getContentLength() 보다 long을 반환하는 getContentLengthLong() 메서드를 사용하는 것이 좋습니다.
가장 직관적인 방법입니다.
찾고 싶은 헤더 이름을 문자열로 넣으면 그 값을 반환합니다.
String contentType = uc.getHeaderField("content-type"); // "text/html"
String date = uc.getHeaderField("date");
서버가 어떤 헤더를 보낼지 미리 알 수 없는 경우,
번호(인덱스)를 이용해 전체 훑기가 가능합니다.
getHeaderFieldKey(int n) // n번째의 헤더의 이름(key)을 반환
// (예: "Content-Type")
getHeaderField(int n) // n번째의 헤더의 값(value)을 반환
// (예: "text/html")
0번 인덱스의 비밀 (중요)
n = 0: 보통 상태 라인(Status Line)을 의미 (HTTP/1.1 200 OK)
getHeaderFieldKey(0)은 null 반환 (Key X)
getHeaderField(0)은 상태 라인 전체 문자열 반환
n = 1부터 실제 헤더 정보가 시작됩니다.
모든 정보가 보고 싶을 때는 getHeaderFieldKey(n)과
getHeaderField(n)을 사용하여 반복문을 돌리면 됩니다.
타입 주의: 모든 반환 값은 문자열(String)이므로, 숫자를 쓰려면 변환 과정이 필요합니다.