TIL - 0525
ajax로 서버에 콜하기
- ajax란?
- asyncronous javascript and xml의 줄임말
- 비동기로 서버에 요청을 하고, 응답 데이터를 받아 랜더링까지 하는 기술 : 백그라운드 작업, 부분적으로 새로고침 효과를 얻을 수 있음
- 응답 데이터로 초기에는 xml을 사용하다가 json을 사용함
- json이란?
- 자바스크립트는 아니지만 자바스크립트의 객체 문법처럼 짜인 데이터
- key - value로 맵핑되어있음 : 변수에 json을 할당하면 변수.key로 value를 찾을 수 있음
- json docs 보기
- xml 대신 json을 사용하는 이유?
- 가벼움 : xml은 마크업 언어로 의미있는 태그 내에 데이터가 감싸져있는 형태 - 필요한 데이터보다 부수적인 데이터 용량이 더 큼
- 필요한 데이터를 파싱하기위해 더 많은 작업을 해야함 :
27 에서 27을 꺼내기위해 찾아가야함
- @RestController : 처리 결과를 뷰 리턴이나 redirect를 리턴하지않고, String을 리턴할 수 있는 컨트롤러 선언 어노테이션
- Jackson 라이브러리 사용을 통해 Entity를 json으로 변환하여 json 데이터를 리턴할 수 있음 : Answer를 리턴해도 라이브러리 덕분에 json으로 변환해서 리턴
- entity의 attribute에 Jackson에서 제공하는 어노테이션 적용을 통해 json 데이터화 하지않을 것을 설정할 수 있음 : 할 것만 설정할 수도 있음
/* controller */
@RestController
@RequestMapping("/api/questions/{questionId}/answers")
public class ApiAnswerController {
private static final Logger log = LoggerFactory.getLogger(ApiAnswerController.class);
@Autowired
private AnswerRepository answerRepo;
@Autowired
private QuestionRepository questionRepo;
@PostMapping
public Answer create(@PathVariable("questionId") Long questionId, String contents, HttpSession session) {
log.info("answer contents : {}", contents);
Answer answer = Answer.builder().user(HttpSessionUtils.getUserFromSession(session).get()).question(questionRepo.findById(questionId).get()).contents(contents).build();
return answerRepo.save(answer);
}
}
/* answer entity */
@NoArgsConstructor
@Getter
@Setter
@ToString
@Entity
public class Answer extends TimeEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(foreignKey = @ForeignKey(name = "fk_answer_user"))
private User user;
@ManyToOne
@JoinColumn(foreignKey = @ForeignKey(name = "fk_answer_question"))
private Question question;
@Column(nullable = false, columnDefinition = "TEXT")
private String contents;
@Column(nullable = false)
@JsonIgnore
private boolean deleted = false;
.
.
.
}
- ajax 요청 - 응답 코드
- ajax 요청 시 콜백함수(응답이 돌아왔을 때) 등록
- JSON 데이터를 파싱할 수 있는 자바스크립트 객체 : JSON
- jquery 적용으로 더 간결하게 코드를 짤 수 있지만 jquery에 의존하는 코드를 짜지않기위해 자바스크립트 문법 그대로 짰음
/* html : trigger */
<form class="submit-write" id="submit-answer" action="/api/questions//answers" method="post">
<div class="form-group" style="padding:14px;">
<textarea id="answer-editor" class="form-control" placeholder="Update your status" name="contents"></textarea>
</div>
<button class="btn btn-success pull-right" type="button" onclick="answerWrite()">답변달기</button>
</form>
/* script.js */
function answerWrite() {
var req = new XMLHttpRequest();
var form = document.getElementById("submit-answer");
req.open('POST', form.action);
req.setRequestHeader('Accept', 'application/json');
req.addEventListener('load', function(){
responseHandle(req);
}, false);
req.send(new FormData(form));
}
function responseHandle(req) {
if (req.status != 200) {
console.log('answer write err!!');
return;
}
var data = JSON.parse(req.responseText);
var arr = [data.user.name, data.modifiedDate, data.contents, data.id, data.question.id, data.id];
var template = document.getElementById('answerTemplate').innerHTML;
for (var i = 0; i < arr.length; i++) {
template = template.replace(new RegExp("{[0-9]}"), arr[i]);
}
var contents = document.createElement('div');
contents.innerHTML = template;
contents = contents.firstElementChild;
document.querySelector(".qna-comment-slipp-articles").prepend(contents);
document.getElementById('answer-editor').value = '';
}
웹 기초
인터넷 : 전세계인을 연결할 수 있는 연결망
- LAN을 먼저 사용했고, LAN을 확장시켜 외부에서도 연결시킬 수 있게 통신망 설비를 갖춤
- 인터넷 사용료를 우리가 내는 이유는 국가에서 특정 통신사에만 통신망을 갖출 수 있게 허가를 내주었기때문에 -> 통신망을 갖춘 통신사에 일정 비용을 내고 외부로 접속할 수 있는 네트워크를 사용할 수 있음
최초의 인터넷을 사용한 웹 통신 : 팀 버너스리 연구소
- 문서를 주고 받기위해 고안해냄
- 프로토콜이 존재함 : HTTP(Hyper Text Transfer Protocol)
- 하이퍼텍스트란 하이퍼링크(A문서 -> B문서로 넘어갈 수 있는 텍스트, 문서 간의 연결)로 작성되어있는 문서
브라우저의 역할
- 최초에는 .html 정적인 문서만 보여줄 수 있었지만 브라우저의 발전으로 더 다양한 문서를 보여줄 수 있게됨
- 브라우저도 프로그램
- 브라우저의 내부 모습 : 랜더링 엔진, 자바스크립트 엔진, 통신(프로토콜 기반 메세지 작성, 실제 통신은 다른 프로그램) 등
- 참고 문서
통신설비 + 클라이언트 + 서버
- 인터넷은 환경이고, 환경을 제대로 사용할 수 있는 프로그램이 클라이언트와 서버 프로그램
- 인터넷이라는 거대한 연결 설비가 갖춰져있지않았다면, 지금처럼 발전된 웹 서비스를 사용하지못했을 것
- 클라이언트와 서버 프로그램의 발전으로 고품질 서비스를 이용할 수 있음
- 웹서버에는 아파치, NginX가 있음
HTTP
- 주고 받기를 하기위해선 서로 간의 약속이 필요함 : 떨어져있기때문에
- HTTP에서 중요한 것
- 무엇 : URI (리소스, 다룰 수 있는 자원 - 자원의 고유값, 예전에는 파일명 그대로를 노출시켰지만 요즘은 리소스명 + 리소스의 id값을 사용함)
- 누구에게 + 무엇을 : URL
- 어떻게할까 : HTTP 메소드
- 어떻게 처리했다 : HTTP 응답코드
CGI
- 동적인 문서 만들기에 관심
- CGI : 그에 따른 웹서버와 프로그램(c와 같은 프로그래밍 언어로 짜여진 프로그램) 간의 통신을 하기위한 약속
- 요청을 받을 때 비로소 프로세스로 되기때문에 동작이 느림
WAS
- CGI 기반 프로그램과 똑같은 역할을 함
- 만들어진 프로그래밍 언어가 다름 : 각각의 WAS 마다 장점이 있음
웹어플리케이션 프레임워크
- 웹어플리케이션 서버 기술을 추상화하여 개발자가 기능 구현에만 집중할 수 있도록 함 : 보통 내장 웹서버가 있음(변경도 가능)
- spring(servlet 추상화), rails(ruby의 웹 관련 API 추상화), express(nodejs에서 제공하는 자바스크립트 API 중 웹 관련 기술 추상화)
IP와 포트번호
- IP는 네트워크에 연결되어있는 기기의 식별자
- 포트번호는 소켓의 식별자 : 포트번호는 약속된 번호 이외에 임의로 지정할 수 있고, 수신자(클라이언트)의 경우에는 프로토콜 스택이라는 통신을 담당하는 OS 프로그램에 의해 통신할 때 임의로 번호가 부여됨(같은 IP에 대한 처리라도 서버에서 받은 제어 정보에 의해 포트번호를 식별할 수 있으므로 각각 응답해줄 수 있음)
쿠키와 세션
- HTTP는 상태를 저장하지않는다 : 상태란 이전 통신의 상태, 이전 요청자가 누군지 이전 응답자가 누군지, 어떤 통신을 했는지 전혀 모른다.
- 단점이라면 요청을 할 때마다 이전에 나야! 라는 것을 알려줘야하는 것
- 해당 단점을 극복하기위해 쿠키라는 것이 고안되었는데 쿠키란 이전 상태값을 저장하기위해 클라이언트에 파일 형태로 저장하는 것을 말함
- 쿠키의 단점이라면 매번 통신할 때마다 이전 통신 상태(ID, 비밀번호 등 민감한 내용들) 서버와 통신할 때 패킷에 실어보내야한다는 것
- 만약 중간에서 누군가 패킷을 들여다본다면? 위험하다
- 그래서 고안된 것이 세션이다 : 세션도 똑같이 쿠키를 사용한다, 그러나 담는 내용이 다름(서버에서 발급해준 세션ID만을)
- 세션 ID가 탈취당하면? 그래서 만료기간을 보통 서버에서 두고 있다(이외에도 인증방법이 또 있겠지 - HTTPS?)
- 보통 만료기간은 프로세스가 종료되었을 때(크롬의 경우 탭마다 프로세스라서 탭이 닫히면 끝)
- 만료기간을 서버에서 설정해줄 수 있음
네트워크
데이터 송수신 동작이 끝나면
- 웹의 경우에는 서버에서 close() 메세지를 보냄 : 서버측에서 TCP 헤더의 컨트롤비트 FIN(1)로 기록하고 패킷을 보냄
- HTTP 1.0은 서버에서 close()가 올 경우 클라이언트에서 끊기 작업에 바로 들어가지만 1.1부터는 리퀘스트 메세지를 보내도 좋도록 되어있음 : 클라이언트에서 먼저 끊기 가능
- 클라이언트에서도 서버의 close() 메세지를 받았다는 확인으로 패킷을 전송함 : ACK 번호(수신측에서 받았다는 의미로)
- 어플리케이션에 데이터를 넘겨줄 대기를 함 : 요청 결과
- 소켓은 바로 없애버리지않음 : 연결이 끊겼다고 하더라도 얼마정도 기다렸다가 소켓을 말소시킴
- 웹의 경우에는 서버가 먼저 close()를 하지만 어플리케이션에 따라 클라이언트가 먼저 close()를 할 때도 있음, close() 패킷을 보낸 후 바로 소켓을 없애버리면 서버에서는 그것도 모른채 확인 패킷을 또 보냈을 경우 해당 IP + 포트가 우연히 일치하는 소켓이 생성되어있다고 했을 때 해당 요청에 대해 FIN을 보내고 연결이 종료되어버릴 수 있기때문에 바로 말소를 시키지않음
- 클라이언트의 포트번호는 임의로 할당됨 : 포트번호는 네트워크 동작을 해야 할당, 문을 열어두는 의미, 결과적으로 어떤 네트워크 프로그램인지 알 수 있음