[Spring] Ch02. Spring MVC - (1) 원격 프로그램 (2) HTTP 요청과 응답(3) 클라이언트와 서버 (4) 텍스트와 바이너리, MIME, Base64
원격 프로그램 실행
로컬 프로그램
java Main
- 자바 인터프리터(java.exe)가 main() 호출
- static 메서드이므로 객체 생성없이 호출 가능
원격 프로그램⭕정의
다른 컴퓨터의 프로그램을 실행하는 것. (클래스)
특징
- 보안 중요
장점
- 저장공간 문제 해결 - 내 컴퓨터에 프로그램 설치 필요 없음.
- 프로그램 업데이트 문제
사용방법 ( 서버의 프로그램 실행방법)
- 원격 호출 가능한 프로그램으로 등록 (= 허용된 프로그램만 외부에서 호출할 수 있게)
- URL과 프로그램을 연결
- 메서드 이름이 중요하지 않음
- 애너테이션이 중요
- url과 연결된 메서드를 호출
- 프로그램 호출
프로그램 (클래스)등록
@Controller 애노테이션을 클래스 앞에 붙임
@Controller
public class Hello {...}
URL과 프로그램 연결
호출하려는 메서드 앞에 @RequestMapping 애너테이션 붙임
외부에서 호출 가능한 메서드. 내부에서는 호출불가.
- /hello 가 url , main가 메서드. 둘을 연결
- System.out.println() 내용은 톰캣 서버의 콘솔에만 출력되며 브라우저에 표시되지 않음.
- 인스턴스 메서드여도 호출이 가능 O
- . 자동으로 누군가 톰캣 내부에서 객체를 생성해주기 떄문.
- private - 외부 컴퓨터에서 호출 가능 O .
- Reflection API 사용 @Controller가 자동 스캔되어 Map에 자동 등록 후 인스턴스 메서드 호출
@RequestMapping("/hello")
public void main() {...}
Reflection API
클래스 정보를 얻고 다룰 수 있는 강력한 기능 제공
java.lang.reflect 패키지 제공
사용 상황
- private인 메서드를 다른 클래스에서 호출
public class Main {
public static void main(String[] args) throws Exception {
// private인 클래스
//HelloController hello = new HelloController();
///hello.main(); // 에러. private 라서 외부 호출 불가.
// The method main() from the type HelloController is not visible
// Reflection API - 클래스의 정보를 얻고 다룰 수 있는 강력한 API 제공
// java.lang.reflect 패키지
// HelloController 클래스의 Class 객체(클래스의 정보를 담고 있는 객체)를 얻어 옴.
Class helloClass = Class.forName("com.fastcampus.ch2.HelloController");
HelloController hello = (HelloController)helloClass.newInstance(); // Class 객체가 가진 정보로 객체 생성
Method main = helloClass.getDeclaredMethod("main");
main.setAccessible(true); // private인 main을 호출가능하게 함
// 호출
main.invoke(hello); // helle.main
}
}
Class 객체
- 클래스의 정보를 담고 있는 객체.
- 해당 정보로 객체를 생성할 수 있음. newInstance() (반환타입 Object)
context root
- project root
- 프로그램과 메서드 연결 시 url에 http ~ /projec명 안적어도 됨.
DAY_OF_WEEK 요일
1: 일요일, 2: 월요일, 3: 화요일, 4: 수요일 …
public static final int SUNDAY = 1;
/**
* Value of the {@link #DAY_OF_WEEK} field indicating
* Monday.
*/
public static final int MONDAY = 2;
target 폴더
- 컴파일된 파일 (*.class) 들어감.
- 우클릭 show in terminal 하면 java 인터프리터로 매개변수 주면서 실행가능
톰캣과 자바 인터프리터 객체 배열
- main()
- 자바 인터프리터가 클래스의 main 호출할 때 매개변수를 문자열 배열 만들고 main()에 전달.
- args 참조변수가 문자열 배열을 참조하면서 main 메서드 내에서 문자열 사용가능
메서드 매개변수 문자열 - url
- 자바 인터프리터, 톰캣 매개변수, url을 가지고 (객쳬)배열 만듦
- spring이 개발자가 작성한 매개변수 기반으로 자동으로 매개변수에 필요한 값이나, 객체를 매개변수에 전달
- 메서드의 매개변수가 이 배열 참조해서 값 사용 가능
URL 구성요소 - 5
Scheme(http) + 서버 이름 (local host) + 포트(8080) + context Path(ch2) + Servlet Path(requestInfo)
- 쿼리 스트링(?year= 2025) 은 포함 X
문자열
HttpServletRequest 클래스
클라이언트가 보낸 요청정보를 담고 있는 객체
HttpServletResponse 클래스
작업 결과를 브라우저로 출력
브라우저에 작업 결과 출력
- 콘텐트 타입 지정
- 인코딩 (텍스트 파일일 때) 지정
- 있어야 한글 깨지지 않음
- response 객체에서 PrintWriter 스트림 얻기
클라이언트와 서버
쿼리 스트링 query string
name, value. Map 형태
- getParameter(”name”) 반환타입 String
- getParameterNames() name들만 뽑음 . 반환타입 Enumeration
- getParameterMap() Map 반환
- getParameterValues(”name”) name이 같은 경우 values 가져오기 String[]
역할에 따른 구분
클라이언트
서비스를 부탁하는 쪽 Request
- 브라우저 클라이언트 Application
- 클라이언트 컴퓨터 (물리)
서버
서비스를 제공하는 쪽 Response
- 서버 컴퓨터 (물리)
ex. Tomcat 서버 Application
- 요청을 받아 응답을 해줌. (서비스를 해줌)
- 자바로 만들어짐.
- 아직 가상 스레드 적용되지 않음 (25/05기준)
- 최신 JDK21 필요 ( 리눅스 바뀌는 것에 따라 JDK도 변함)
가상 스레드
- 웹 서버에 최적화됨
- 가짜 스레드 - I/O작업이 많을 때 유용하다
- 웹서버는 I/O 집중적인 작업
CPU 집중적인 작업과 I/O 집중적인 작업이 있음.
- CPU 집중 작업 - 압축, 작업
- I/O 집중 작업 - 파일 주고 받기 → 웹서버는 다 이거임.
- CPU - x100 → RAM - x1000 → HDD
서버 종류 - 어떤 서비스를 제공
이메일 서버
- 텍스트 제공해줌.
웹서버
- 웹을 서비스한다.
- 웹 = 리소스(콘텐츠)의 연결 ⭕ 암기
- 거미줄 처럼 리소스가 연결 되어 있음
- 파일이 아닌 것도 있기 때문에 리소스라고 부른다.
- 거의 파일과 같다.
하이퍼 텍스트 = 문서간 연결
- 링크 <a> 가 있어 직접 주소를 입력하지 않고 리소스를 볼 수 있음(연결되어 볼수있음)
포트 port
- 하나의 컴퓨터 안의 프로그램 구별
- 클라이언트의 어느 서버에 대한 요청인지 구별
- 서버의 ip와 port가 고정(바인딩, 연결)되어 있어야 클라이언트가 접속할 수 있음
- 웹서버 80 기본 생략 가능
- Listening 서버가 n port에서요청 기다리고 있음.
ex. 대표전화(pc) 1588-8888 내선 번호(port) #1234 #1111
종류
- well known 0 ~ 1023 사용 x
- 65,535개 사용가능
WAS ⭕ 암기 ex. 톰캣
Web Application Server ‘웹’ 프로그램을 사용할 수 있게 제공함
- Web Application
- 내가 로컬에 설치하지 않고 서버에 프로그램을 설치해 클라이언트가 웹 브라우저를 통해 사용할 수 있는 프로그램
- Application 프로그램
장점
- 업데이트 용이 - 서버만 업데이트
ex. 구글 스프레드 시트
- 내가 직접 설치하지 않은 프로그램임에도 브라우저를 통해 내 컴퓨터에 프로그램을 설치한 것처럼 사용할 수 있음
- 직접 설치하면 저장공간과 업데이트를 내가 관리해야함
ex. MSFT가 브라우저의 발전을 막은 이유
확장 프로그램 vs. 플러그인
- 확장프로그램 웹 브라우저에 돌아갈 수 있는 프로그램을 로컬에 설치
- 플러그인 브라우저의 보조 기능 제공
URL 호출
- URL과 연결된 메서드 호출. 일 시킴.
- 프로그램이 그때그때 결과를 만들어줌
- 화면을 계산해서 줌
- HTTP 프로토콜 빠른 전송을 위해 발전 중
Tomcat 내부구조 ⭕ 구조 이해
구성 요소
Service
- Connector
- 요청 프로토콜에 따라 Connector 종류 다름
- 요청을 Engine에 전달
- Engine
- Host 여러 개 가능
- 1개의 Host안에 Context 여러개 가능
- Context 하나의 웹 애플리케이션 ex. /ch2, /ch3 sts spring 프로젝트
- 서로 독립적인 공간에 프로젝트가 돌아감
- Servlet 작은 서버 프로그램
- 서버에서 실행되는 프로그램
- ex. Controller url과 연결된 서블릿 실행
- 서블릿이 클라이언트에게 응답 전달
- Host 여러 개 가능
설정 파일 server.xml, web.xml
설정 파일 읽는 과정
서버 파일 설치 /conf/server.xml 톰캣 서버 설정 파일
- 모든 웹앱 공통 설정 (tomcat)/conf/web.xml설치
- 각 웹앱 프로젝트 개별 설정 /WEB-INF/web.xml 설치
- 공통 설정을 덮어쓰기함. 반대도 가능
설정 파일 보는 법
- 패키지 폴더의 servers 폴더
- apache-tomcat의 폴더에서 conf 폴더를 복사하여 사용함
- Tomcat 프로그램 공유하면서 서버 설정만 다른 여러 서버 등록 가능
server.xml
port 를 80으로 바꾸면 요청 시 8080 안 붙여도됨.
<Connector connectionTimeout="20000" maxParameterCount="1000" port="80" protocol="HTTP/1.1" redirectPort="8443"/>
http://localhost/ch2/rollDice
Engine
여러 Host 포함 가능
<Engine defaultHost="localhost" name="Catalina">
Host ex. www.fastcampus.com
- unpackWAR war 파일로 배포 시 자동 압축 풀어라 (true)
- webapps 폴더 tomcat의 war 파일 저장소
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
Context
<Context docBase="ch2" path="/ch2" reloadable="true" source="org.eclipse.jst.jee.server:ch2"/></Host>
web.xml 공통 설정
원격 프로그램 등록 xml 등록 → @Controller 애너테이션으로 등록 (둘중 하나)
- 서블릿 등록 ⇒ @Controller
- url 연결 부분 ⇒ @RequestMapping
서블릿 등록
<servlet>
<servlet-name>default</servlet-name>
<servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
URL 연결
- appServlet 이름을 패턴과 연결 / (주소 연결 아님)
<!-- The mapping for the default servlet -->
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
HTTP 요청과 응답 - 이론
프로토콜 protocol ⭕
data 통신에서의 공통 약속(법), 규칙
- 주고 받을 데이터 형식 정의
- ex. 010010101 몇자리 잘라서 읽어라
- 유사 . Text → 인코딩
HTTP
- 문서를 보내기 위한 프로토콜
- 텍스트 기반
- 읽기 쉬움
HTTP 특징 -3 ⭕
- Text 기반
- HTTP 3.0부터 바이너리 기반으로 바뀔 것. 현재는 텍스트 기반임.
- 저장할 때 변환 발생하는 것 막기 위해
- Stateless ex. 의사 모든 환자 치료
- 누가 요청했는지 기록하지 않음. → 보완 : 쿠키 & 세션
- Connectionless
- html 파일 하나 요청처리만 하면 html 문서 안에 연결된 요청을 각각 따로 보냄.
- 연결 계속 해야하는 오버헤드 발생
- 현재는 연결을 유지하는 편임.
- 요청이 한번 왔다가면 연결을 끊어버림. → 발전중임
HTTP 메세지
- status 상태
- header 헤더
- Key: Value 형식
- 빈줄이 있어야 헤더와 바디 구분
- body 바디
- 실제 내용
특징
- 확장 가능 - 커스텀 헤더 추가 가능
- 형태 헤더 이름 : 값
- 헤더와 바디는 빈줄로 구분 . 헤더 길이 가변적
ex. 편지 형식
상태코드 ⭕ 암기
- 100 HTTP/1.1 추가 . 정보 교환 목적
- 200 성공
- 300 재요청. 다른 url로 요청하라고 응답
- 400 클라이언트 에러.
- 500 서버 에러. 요청은 OK. 서버 처리 중 에러
GET Read (리소스)읽기
- body에 html 없음.
- 소용량 데이터 쿼리 스트링으로 전달
- URL에 몇글자 들어가나? 8K (8천자) URL 인코딩 vs. base64
- 간단한 문서 저장 가능
- 장점 : 공유 유리
- 단점 : 보안 취약
- 서버의 리소스 읽어오기
ex. 검색엔진에서 검색 단어 전송
POST Write 쓰기
- (body)에서버에 전송할 data( html )작성
- 대용량 데이터 전달
- 첨부파일
- 보안 유리
- POST 했다고 보안이 되는 것은 아니고 TLS 암호화 해야함.(HTTPS)
ex. 글쓰기, 로그인, 회원가입, 파일첨부
General Header
요청라인 뺀 Request Header
idempotence 멱등
- 읽기는 여러번 요청해도 문제 없음
- 쓰기는 여러번 요청 시 문제 있음. 멱등이 아닐 수 있다
- 결제 요청 3번 처리
텍스트와 바이너리, MIME, Base64
⭕ 바이너리 파일vs. 텍스트 파일 면접
바이너리 파일
문자와 숫자가 저장
- 숫자는 숫자로, 문자는 문자로 저장.
- 변환 없이 저장해 빠름
특징
- 메모장으로 봤을 때 읽기 어려운 경우
텍스트 파일
전부다 문자. 숫자 없음
- 숫자 → 문자 : 텍스트 파일에는 숫자를 다 쪼개서 저장 - 변환 발생
- “1 2 3 “ → ‘1’ ‘2’ ‘3’
- 문자 -/→숫자 : 어떤 애가 숫자인지 몰라서 변환 불가
숫자 123 UTF8
- 4바이트 바이너리
- 텍스트 저장 시 3바이트
특징
- 읽을 수 있는 경우 텍스트 파일
MIME
HTTP가 텍스트 기반 프로토콜임에도 바이너리 파일도 전송하기 위해 전송할 데이터 타입을 작성
- 타입/서브타입
response.setContentType("text/html"); // 데이터 타입 지정
// img/bmp로 하면 실제 데이터는 html임에도 img로 해석
out.println("<html>"); // 실제 데이터
Content Type
- 바이너리 파일 타입
- 바이너리 파일이 텍스트로 저장되면서, 변환된 텍스트에서 바이너리가 어떤 타입인지 알기 위해 사용
- 타입을 알고 나서 다시 바이너리로 변환하여 브라우저가 계산할 수 있게 함.
base 64⭕ 면접
이미지 전송을 위해 바이너리를 텍스트로 변환하는 방법
- 64진법 a - z 26개 + 26개 , 0-9 10개
- 6bit를 문자 1개로 표현 $2^6$
- 단점 : 문자 1개 표현위한 저장 공간 증가.
주의 사항
- 이진 데이터를 “의미 있는 숫자 단위”로 자르는 게 아니라,
- 언제나 3바이트씩(24비트) 모아서 6비트씩 4조각으로 나눈 뒤, 부족한 부분은 = 패딩으로 채우는 방식
목적 이미지 전송 방법
정적 파일 종류 - 접근 방식 기준
- src/main/webapp (WEB-INF 밖): 정적 리소스 + 직접 호출 가능한 JSP
- src/main/webapp/WEB-INF: 외부 접근 차단, 설정·템플릿·클래스패스 전용