1. putty 설치하기

https://putty.en.softonic.com/

 

2. AWS의 EC2 설정 및 키페어 생성하기 (.pem으로 받기)

 

3. putty 설치 파일 위치에서 puttygen클릭, AWS에서 받아온 키파일 로드 (pem -> ppk 변환하기)

 

(정상적으로 됬을경우 해당 alert 출력)

 

4.현 상태에서 save private key 클릭하여 저장

5. putty 실행하여 HostName은 AWS의 IPv4 복붙

 

6. putty 좌측 카테고리의 Connection- SSH - Auth - Credential의 Private Key File에 아까 puttygen으로 생성한 ppk파일 등록 후 오픈 (모든 설정을 마치고 Session의 Saved Sessions탭의 save,load를 누르면 현재 설정을 저장 및 로드가 가능하다.)

 

7. open을 눌렀을시 해당 창이 나타나며 ubuntu를 입력했을때 문제가 ㅇ벗다면 AWS의 ip가 나타나며 연결완료

'Spring' 카테고리의 다른 글

카카오 api 로그인  (0) 2024.02.04
Mybatis, BulkInsert  (0) 2024.02.01
Spring MVC의 핵심 애노테이션  (0) 2024.01.26
SSR, CSR, SSG  (0) 2024.01.23
개인 프로젝트 회고  (0) 2024.01.21

 

 

@RequestMapping

  •  @RequestMapping은 특정 HTTP 요청(예: GET, POST, PUT, DELETE 등)을 컨트롤러의 메소드에 매핑합니다. 이를 통해 해당 요청이 들어왔을 때 어떤 메소드가 처리할지 정의할 수 있습니다.
  • 즉, 우리가 front에서 페이지를 통해 무언가의 작업 (form 제출, 버튼 클릭 등)을 실행했고 이를 Back의 어디서 제어를 담당할지 정해야 하는데 이부분을 정해주는게 해당 어노테이션이다.
  • URL 패턴(value="/users"), HTTP 메소드(get,put,delete,post), 헤더, 매개변수(MemberVO membervo) 등을 지정할 수 있습니다.
@RequestMapping("/users")
public String getUsers() {
    // 사용자 목록을 반환하는 로직
}

@RequestMapping(value = "/users", method = RequestMethod.GET)
public String getUsers(MemberVO membervo) {
    // 사용자 목록을 반환하는 로직
}

 

@PathVariable

  • @PathVariable은 URL 경로의 일부를 변수로 추출하여 파라미터로 사용이 가능하도록 해준다.
  • URL패턴인 /users/{userId} 에서 {userId} 부분을 추출하여 메소드에 전달, 이것을 파라미터로 사용이 가능하다
  • 즉, 하단의 예시코드는 gifticonDelete/{gifticon_id}으로 요청이 들어왔을때 gifticon_id을 활용하는 형식이다.
  • URL의 예시 : /users/123
@RequestMapping(value = "/users/{userId}", method = RequestMethod.GET)
public String getUserById(@PathVariable("userId") Long userId) {
    // userId = 123
}

//예시
@RequestMapping("/gifticonDelete/{gifticon_id}")
	public String gifticonDelete(@PathVariable("gifticon_id") int gifticon_id) {
		gifticonService.gifticonDelete(gifticon_id);
		return "redirect:/shop";
}

 

 

@RequestParam

  • 사용자가 전달하는 값을 매개변수로 1:1 매핑이 가능하도록 해주는 어노테이션.
  • 한번에 여러개의 값의 사용해야 할땐 ModelAttribute이 더 낫다. -> 만일 RequestParam이 1개가 아닌 여러개일때 나중에 이를 재사용하기 힘들어진다.
//URL의 예시 : /users?id=admin
@RequestMapping("/users")
public String exgetUsers(@RequestParam("id") String userId) {
    // userId = admin
    //URL에선 id로 나타나지만 다른형식으로 변환해서 사용하고 싶을때 "("기본이름") 원하는이름"의 형태이다.
}

// URL예시 : /users?id=123&name=John&email=john@example.com&phone=010-1234-5678
@RequestMapping("/users")
public String exgetUsers2(@RequestParam String id, @RequestParam String name,
                              @RequestParam String email,
                              @RequestParam String phone) {
    // id = 123
    // name = John
    // email = john@example.com
    // phone = 010-1234-5678
}

@ModelAttribute

  • 전체 데이터를 받아 객체로 매핑할 때 사용한다.
  • 한번에 여러 데이터가 오가는 폼에서 자주 사용되는 경우가 많다.
  • 해당 어노테이션은 스프링에서 생략하여도 자동적으로 붙
@PostMapping("/register")
public String register(@ModelAttribute MemberVO membervo) {
    // membervo 객체를 사용하는 로직
}

public String register(MemberVO membervo) {
    // 이렇게 해도 무방하다
}

 

ResponseEntity

  • HTTP 응답의 본문, 상태 코드, 헤더 등을 전체적으로 제어할 수 있게 해주는 클래스
  • void를 사용한 ajax의 경우 문제없이 작동하더라도 return할게 없을때 error가 나타나는데 해당 방식을 활용하면 끝남과 동시에 http 코드도 함께 전달이 가능해져서 error가 나타나지 않게된다.
@GetMapping("/user/{id}")
public ResponseEntity<User> getUserById(@PathVariable("id") Long userId) {
    User user = MemberDAO.getmember(userId);
    return ResponseEntity.ok(user); // 200 OK 응답과 함께 유저 반환
}

 

HttpServletRequest

front에서 back으로 데이터를 보냈을때 보내지는 데이터(헤더, 쿠키, 세션 등)가 캡슐화가 되어 전달된다.

@GetMapping("/example")
public String handleRequest(HttpServletRequest request) {
    String clientIP = request.getRemoteAddr(); // 클라이언트 IP 주소 가져오기
    // HttpServletRequest를 사용한 다른 로직
    return "viewName";
}

'Spring' 카테고리의 다른 글

Mybatis, BulkInsert  (0) 2024.02.01
putty를 활용해 EC2에 접근하기  (0) 2024.02.01
SSR, CSR, SSG  (0) 2024.01.23
개인 프로젝트 회고  (0) 2024.01.21
SMTP를 활용하여 이메일 보내기  (0) 2024.01.04

크로스 도메인 (Cross Domain) - 서로 다른 도메인간 호출로 주로 AJAX를 활용해 타 사이트의 데이터를 크롤링해올때 데이터의 도용 및 각종 보안문제를 야기하는데 이를 막기위해 Cross-Origin HTTP요청을 제한하는 것이다

 

동일출처정책 (SOP, Same Origin Policy)

  • 상단의 크로스 도메인으로 인하여 코드 탈취 및 악용의 여지를 없애기 위해 만들어진 정책으로 동일한 출처의 접속만 리소스에 접근하도록 제한하는것
  • SOP가 적용되지 않을경우 사용자는 A사이트에 로그인후 인증토큰을 받고 이것이 유효한 상태로 B사이트에 방문할경우 B 사이트의 스크립트는 사용자 브라우저를 통해 A 사이트인증토큰에 접근이 가능하게된다. A사이트의 토큰을 B사이트에서 악용할수 있다는 점이다.
  • http://example.com:80 http://example.com:8080 는 포트번호가 다른데 SOP에 따라 서로 다른 출처로 간주된다
  • AJAX를 통한 크롤링이 늘어나면서 SOP를 따질경우 제약이 너무 많아지기에 CORS정책이 나오게 되었다. 
  • 개발자도구 - network 탭에서 Access-Control-Allow-Origin란 헤더가 없을경우 다음과 같은 에러가 나타나게된다.
//크로스도메인 에러
XMLHttpRequest cannot load http://www.abc.co.kr.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://cvb.abc.co.kr' is therefore not allowed access.

 

프로토콜 - 연결,통신 데이터 전송을 제어하는 일련의 규칙 및 표준 (http, https...)

스킴 (Scheme)- URL체계 최상위 레벨로 특정 프로토콜의 이름

  • http: 일반적인 웹 페이지에 접근하기 위한 HTTP 프로토콜.
  • https: 보안 웹 페이지에 접근하기 위한 HTTP Secure 프로토콜.
  • ftp: 파일 전송 프로토콜(FTP)을 사용하여 파일을 전송하거나 다운로드할 때 사용.
  • mailto: 이메일 주소를 지정하고 이메일 클라이언트를 열 때 사용.

크로스 도메인 이슈 (CORS, Cross Origin Resource Sharing)

  • HTTP헤더 기반 매커니즘으로 동일 출처 이외의 다른출처도 접근할수 있도록 하는 기능 -> 다른 사이트의 코드를 허가없이 도용하는걸 방지하기 위함
  • 만일 CORS정책을 지키지 않은상태로 다른 출처가 리소스의 로드를 요청할경우 SOP에 의해 거부, 리소스가 차단
  • 서버가 실제 요청을 허용하는지 확인을 위해 브라우저가 원본간 리소스를 호스팅하는 서버에 "실행전" 요청 매커니즘에 의존한다.
  • 브라우저에서 두번쨰 요청 도메인이 처음 요청을 받고 응답한 사이트의 도메인에 포함된 URL이 아닐경우 에러
  • Simple request, Pre-flighted request 2종류로 나뉜다.

 

Simple request (간단한 요청)

pre-flighted 없이 GET,HAED,POST중 1가지 방식이며 POST는 content-type이 하단과 같은경우에만 허용된다.

  • application/x-www-form-unlencoded, 
  • multipart/form-data
  • text/plain
  • 클라이언트가 요청을 보낼경우 브라우저는 CORS에 대한 헤더를 추가하여 서버에 전달 -> 서버가 헤더 확인후 Origin(출처)값이 허용된다면 요청 헤더의 Access-Control-Allow-Origin를 Origin 값으로 설정한뒤 브라우저에 보낸다 -> 브라우저는 Access-Control-Allow-Origin가 탭의 출처와 일치하는지 확인한다 (와일드카드도 적용된다) 

Preflighted Request (사전 요청)

복잡한 요청을 보내기전 브라우저가 OPTIONS 메서드를 사용하여 서버가 해당 요청을 수용할 수 있는지 확인하는 것입니다.

  • 요청을 보낸다 -> 서버는 Access-Control-Allow-Origing헤더를 참고하여 SOP를 검증 -> 브라우저는 CORS 요청을 보낸다 -> 해당 요청이 허용된경우 실제 요청 처리
  • JSON방식으로 데이터를 가져올떈 SOP에 영향을 받지만 JS, CSS파일은 SOP에 영향을 받지 않으므로 JS파일 내부에서 JSON형식으로 파싱해 사용가능
  • 클라이언트는 브라우저 실행옵션, 플러그인을 활용해 CORS 회피(무시) -> 브라우저가 진행하는것이기에 문제없다

 

사이트간 스크립팅 (XSS, Cross-site scripting)

웹사이트의 관리자 이외의 사람이 웹페이지에 악성 스크립트를 삽입할수 있는 취약점으로 주로 게시판에 악성스크립트가 담긴 글을 올리는 형태이다. (웹페이지 일부를 다른 사이트로 링크 및 악성코드를 심어 피싱사이트로 유도)

 

비지속적 XSS (Non-persistent) - 클라이언트가 제공하는 HTTP쿼리 매개변수에 적절치 않은 결과를 페이지에 출력하는것 (반사형 XSS라고도 한다.)

  • 검증되지 않은 사용자가 URL파라미터, HTTP요청 헤더정보를 수정해 공격하는것으로 주로 사용되는건 검색엔진의 검색창이다
  • 검색엔진의 검색창에서 문자열을 검색하는경우 이것은 결과페이지(url)에 나타나게 되는데 
  • 주로 피해자에게 입력받은 검색어를 표시하는곳, 입력한 값을 오류메세지와 같이 보여주는곳에 스크립트를 삽입하며 이때 입력값을 포함해 응답을 전송할때 실행한다. (피해자가 직접 스크립트를 실행하도록 유도하기에 1회성 공격이라 할수있다)
  •  

 

 지속적 XSS (persistent XXS) - 공격자(A)가 기존 페이지에 악성코드를 삽입, 서버의 DB에 저장되는데 이것이 다른 사용자(B,C,D,..)에게 정상적인 페이지처럼 계속 출력되는것

  • 악성 스크립트 삽입 -> 서버에 저장 -> 다른 사용자에게 전달 -> 실행 및 영향
  • 다른 사용자는 이것이 출처가 분명한 사이트에서 받아왔기에 문제가 없다고 생각하지만 실질적으론 (A)의 악성코드도 같이 가져오는 것이며 쿠키를 탈취당하거나 타 사이트로 리다이렉션되는 방식이다. 

 

참고링크 : https://coding-maggot.tistory.com/100

'CS' 카테고리의 다른 글

코딩 용어모음  (0) 2024.08.23
JS파일 가져오기 로컬, 원격 차이  (0) 2024.08.03
IP, DNS, HTTP  (0) 2023.07.09
HTTP 헤더  (0) 2023.05.06
난독화  (0) 2023.05.03

브라우저에 화면이 출력되는건 알았지만 이게 서버, 클라이언트 어디서 작업을 하는지 궁금했고 어디서 사용하는게 더욱 효율적인지 궁금하여 포스팅한다.

 

렌더링 -> 서버로부터 요청받은 내용을 브라우저에 표시해주는것

서버사이드 Server-Side Rendering

웹사이트 기준으로 서버측(개발자측)에서 사용자(클라이언트)에게 보여줄 페이지를 작업해서 보내주는 방식이며 과거 naver에서 모바일 블로그를 작성했을때 사용한 형식이라고 한다.

 

해당 방식은 모든 데이터가 매핑된 서비스페이지를 클라이언트에게 보여주기에 페이지를 구성하는 속도는 느려지나 사용자에게 보여주는 콘텐츠의 구성이 완료되는 시점이 빨라지며 SEO 또한 이점을 갖게된다.

(웹페이지 로딩시 한번에 화면 전체가 나오는게 아닌 화면에 뭔가 하나씩 나타나는 형태이다.)

 

 

순서

1. 클라이언트의 요청으로 서버에 웹페이지 및 특정 리소스를 요청하며 시작

2. 서버처리 - DB쿼리, 서버측 스크립트 실행 및 데이터를 HTML로 조립 및 HTML 생성

3. 응답전송 - HTML파일을 HTTP 응답으로 클라이언트에 전달

4. 브라우저 렌더링 - 브라우저가 해당 HTML응답을 받아 렌더링 및 화면출력

 

출처 : The Benefits of Server Side Rendering Over Client Side Rendering

 

 

장점

1. 데이터의 위조 가능성이 현저하게 줄어든다

2. 데이터 처리를 서버에서 담당하기에 클라이언트의 리소스 부담이 줄어든다.

3. SEO 성능의 향상 (검색엔진이 해당 페이지를 쉽게 크롤링가능 -> SEO는 밑에서 설명)

 

단점

1. 서버가 작업을 전담해서 작업하기에 많은 자원이 소모된다.

2. 새 페이지를 요청할떄마다 서버가 처리하고 응답하기에 서버가 느릴경우 지연이 발생한다.

 

 

클라이언트 사이드 Client-side Rendering

클라이언트가 입력한것을 수신해 데이터만 넘어온 상태에서 JS가 HTML로 만들고 이를 애플리케이션에서 해석해서 표시하는것이다.

초기 전송되는 페이지의 속도는 빠르나 서비스에서 필요한 데이터를 클라이언트에서 추가로 요청하고 재구성하기에 실제 페이지 완료시점은 SSR보다 느려진한다

(즉, 일단 다 받아오고 조립하는 형식으로 하얀화면이 오래 나타난다)

출처 : The Benefits of Server Side Rendering Over Client Side Rendering

 

 

장점

1. 서버 유지비용이 줄어든다.

2. 로딩된후 페이지간 전환시 새로운 페이지를 서버에 요청할 필요없이 더 빠른 화면전환이 가능하다.

3. 네트워크가 끊기더라도 일부 기능의 유지가 가능하다 

 

단점

1. SEO 성능이 낮다.

2. 클라이언트에서 데이터 처리가 이뤄지기에 보안상 비즈니스 로직이 공개될 우려가 있다..

3. 동적인 데이터의 경우 CSR은 서버에 계속 데이터에 대한 요청을 보내는데 이로인해 대기시간이 생긴다.

클라이언트 컴퓨터의 처리 부담이 많아진다.

 

정적 사이트 생성 Static Site Generation

최근에 각광받는 방식으로 각 페이지를 빌드시점에 정적파일로 생성하고 클라이언트가 요청할때 이것을 넘겨주는 형식이다.

그리고 이것은 CDN과 연관되는데 SSG와 합쳐져 더욱 빠른속도의 로딩이 워지는것이다.

CDN(Content Delivery Network) - 서버에서 사용자가 요청하는 콘텐츠를 캐싱해두고 가까운 위치에서 콘텐츠를 제공하는 역할

구글의 CDN 예시

장점

1. 사전에 생성된 파일(정적파일)을 제공하기에 앞서말한 2개의 방법보다 훨씬 빠른 속도를 보여준다.

2. 정적이라 서버쪽 스크립트 실행이 없어 파고들 보안 취약점이 줄어든다. (하이재킹, 인젝션 공격, XSS 등..)

 

단점

1. 사전에 생성된 정적파일이라 실시간 변화하는 콘텐츠, 인터렉션 처리엔 제한요소가 생긴다.

2. 빌드 과정이 길어지며 새로운 콘텐츠 추가, 업데이트시 전체 사이트를 재빌드 해야한다.

 

SEO

SEO는 검색엔진 최적화로 검색엔진은 웹을 크롤링 -> 콘텐츠 수집 -> 결과페이지 출력의 순서를 갖는데

여기서 콘텐츠를 크롤링하는 시점에서 웹페이지의 HTML을 보고 구조, 콘텐츠, 링크등을 이해하고 나름의 우선순위를 매겨 더 상위권에 노출되는 형태이다.

그리고 SSR의 경우 서버에서 직접 HTML을 가공해서 보내기 때문에 SEO 입장에선 훨씬 더 쉽게 크롤링이 가능하기 때문에 최적화가 가능해진다는 것이다.

 

결론

요약하자면

비교대상 SSR CSR SSG+CDN
속도(초기 로딩속도) 보통 느림 가장 빠름
비용 중간 가장 쌈 가장 비쌈
SEO 우수(SSG와 동일) 낮음 우수(SSR과 동일)
보안 중간 낮음 가장 높음

 

다음의 표가 나타난다.

 

이를 토대로 naver가 17년에 CSR -> SSR로 변경을 하였는데 그이유를 나름대로 생각해보았다.

 

1. 특이 케이스의 문제

Naver라고 하더라도 많은 유저의 사람들이 이용하는 이상 특이 케이스에 대한 대응법 (2024년인데 아직 갤럭시S2를 쓴다던가 하는 케이스)을 만들어야했고 모든 케이스에 대응하는 방식보단 서버쪽에서 일괄적으로 만들어 넘겨주는SSR이 훨썬 더 효율적인 방식이라서 그런것 같다.

 

2. 대기시간의 최소화

구글 리서치에 따르면 웹사이트의 로딩시간이 3초가 넘어가는 시점부터 접속자 30% 이상이 해당 페이지를 이탈하며

5초부턴 90% 이상이 이탈하는 경향이 있다고 한다.

유저이탈을 방지하기위해 구글에선 공룡이 점프하는 게임을 제작했다고 생각한다.

네이버 또한 리서치 결과를 토대로 시간이 조금 오래 걸리지만 화면에서 무언가 출력되는 모습을 보이기 위해 해당 방식을 사용했다고 생각한다.

 

마지막으로 성능상 직접 진행해본사람의 글로 포스팅을 끝내겠다


조건 : JS파일을 CDN에서 받는경우

CSR

소요시간 : 24~50ms

(API 서버에 데이터를 요청했을떄)AWS 데이터 센터 : 117ms ,GCP : 70ms

SSR

소요시간 : 70ms

CSR이 SSR보다 약 2.9배 빠르게 html쉘을 렌더링 하였다.

DB와 여러번 통신을 주고받아야 할경우 SSR이 DB와 물리적으로 가까운 서버에서 실행되기에 CSR보다 유리하다

 

 

참고링크 : https://blog.rightbrain.co.kr/?p=12479

참고링크 : https://velog.io/@ragi/Back-end-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8-%EC%82%AC%EC%9D%B4%EB%93%9C-%EC%84%9C%EB%B2%84%EC%82%AC%EC%9D%B4%EB%93%9C

참고링크 : https://d2.naver.com/helloworld/7804182

'Spring' 카테고리의 다른 글

putty를 활용해 EC2에 접근하기  (0) 2024.02.01
Spring MVC의 핵심 애노테이션  (0) 2024.01.26
개인 프로젝트 회고  (0) 2024.01.21
SMTP를 활용하여 이메일 보내기  (0) 2024.01.04
인스타 API 연동하기  (0) 2023.08.23

1인 개발로  진행한 프로젝트를 끝내게 되었다.

이를 기념하여 저장용 게시글을 남긴다.

 

기획의도

1. 교육과정을 마쳤지만 이대로 취업했을때 아무것도 없는 처음부터 구현하라고 하면 오래 걸릴것 같았다.

2. 팀 프로젝트의 진행과정에서 코드리뷰를 몇번 진행했으나 서로의 코드가 이해안되는 경우가 있었고 또한 각자 기능을 나눠서 개발하다보니 해당 기능에 대해 물어봐도 서로 질문하기도 알려주기도 애매했던 기억이 있었다.

3. 처음 개발을 진행했기에 처음에 알려준 방법으로만 Front와 Back 사이의 데이터를 교환하는 방식만 사용했는데 다른방식은 없었을까?

3개의 이유로 혼자서 구현한 프로젝트가 있었으면 해서 개발을 진행하게 되었다.

 

그중에서 내가 애용하던 설문조사 사이트와 기프티콘 판매 사이트가 떠올랐고 이것 2가지를 합쳐 개발하기로 하였다.

(한국 서베이 -> 설문조사 사이트, 기프티스타 -> 기프티콘 할인 사이트, 오피스콘 -> 기업용 기프티콘 할인 사이트)

 

차별점

  • 기존 설문조사 방식은 기업 담당자가 사이트 관리자와 협의하고 관리자가 직접 만드는 형식이었으나 이를 기업 담당자 혼자 CRUD가 가능하도록 변경
  • 포인트제를 활용해 기프티콘 구매가능

있으면 좋겠다 싶은점 (나중에 추가하면 좋을거 같은점)

  • 기프티콘 구매시 유효기간별 차등 할인이 있으면 좋을거 같다.  -> IMG의 텍스트 추출방식도 생각해봤으나 각 기프티콘마다 날짜 형식도 달랐고, 타 사이트는 실제 관리자 하나씩 검수하여 업로드 하는 형태이다
  • 각 User, Admin도 안쓰는 기프티콘을 판매가 가능하도록 하면 좋을거 같다. -> 포인트의 현금화가 필요한데 이건 실제 돈나갈까봐 무섭다.. // 기프티콘 쓴건지 안쓴건지 하나씩 확인해야하는 문제가 생길거 같다.

 

권한레벨

  • User - 설문조사, 공지사항, 기프트샵 접근가능
  • ADMIN - User + 본인의 설문조사 CRUD 접근가능
  • MASTER - ADMIN + 기프트샵, 전체 설문조사, 공지사항 CRUD 접근가능

member 관련 기능

  • 스프링 시큐리티 활용 회원가입, 비밀번호 암호화(machers를 활용해 검사)
  • 로그인 및 세션에 ID 저장
  • 아이디 / 비밀번호 찾기 기능 (google의 SMTP 활용)


설문 관련 기능

  • 각 담당자 및 Master만 수정 및 삭제 가능
  • 결과페이지는 DB에 CSV 추출하는 형식으로 변경 (질문형의 경우 이것을 배치할 방법이 안떠올라 해당 방식으로 미구현)
  • 설문 완료시 각 User의 리워드가 누적되며 이를 통해 기프티콘 구매가능


리워드 관련 기능

  • 기프티콘 업로드
  • 설문조사를 통한 리워드 획득, 이를 통해 굿즈샵에서 기프티콘 구매, mypage에서 확인가능

공지사항 관련 기능

  • 게시판 CRUD 


느낀점 및 아쉬웠점

  • 프론트, 디자인에 구현이 어려웠다.
  • JS 부분은 내가 모르는 부분이었고 실질적인 구현에 너무 많은 시간이 할애되었다. (GPT 활용)
  • doc의 중요성을 크게 못느껴 작성을 안했는데 나중에 어떤게 어떤기능이고 왜 이렇게 쓴건지 하나씩 차아볼떄 불편했다.
  • 1인 개발의 경우 의견교환 등 어렵기떄문에 가독성 좋은 코드 보단 나만 알아보면 좋겠지 싶은 코드 위주로 짜게 되는게 컸다.
  • 저장은 적어도 3번은 누르자!..

추가로 생긴 호기심

  • 서버에서 작업을 할당하는것과 클라이언트에 작업을 할당하는것 어느것이 좋을까? (SSR 게시글 참조)
  • 어느정도 수준에서 기능, 완성도와 타협하는게 맞을까?
  • MVC로 구현하는것도 괜찮긴 했지만 실제로 여러 Service를 사용하니 이것대로 이게 어떤걸 반환하고 실제로 어떤 로직인기 찾기 어려웠다. 더 나은 방식은 없었을까?
  •  Back과 Front 사이의 데이터를 주고받을떄 model로 데이터를 넘기는 방식을 주로 사용했는데 더 나은 방식은 없었을까? 

'Spring' 카테고리의 다른 글

putty를 활용해 EC2에 접근하기  (0) 2024.02.01
Spring MVC의 핵심 애노테이션  (0) 2024.01.26
SSR, CSR, SSG  (0) 2024.01.23
SMTP를 활용하여 이메일 보내기  (0) 2024.01.04
인스타 API 연동하기  (0) 2023.08.23

회원가입 구현시 ID/PW가 잃어버렸을때 이메일 인증 및 검증로직이 필요하여 작성

 

설정파일 (pom.xml)

<dependency>
			<groupId>javax.mail</groupId>
			<artifactId>mail</artifactId>
			<version>1.4.7</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context-support</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

 

  • alt+F5로 업데이트 해줄것
  • javax.mail -> 스프링에서 제공하는 메일 관련 라이브러리
  • spring-context-support  -> JavaMail 에 대한 추상화 기능을 제공하며 밑의 service에서 MailSender를 사용하기 위해서 입력

설정파일 (root-context)

<!-- username과 password의 value에는 사용할 자신의 네이버 또는 구글의 ID와 비밀번호 -->
	<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
		<property name="host" value="smtp.gmail.com"/>
	    <property name="port" value="587"/>
	    <property name="username" value="(내 id)"/>
	    <property name="password" value="(PW)"/>
	    <!-- 보안연결 SSL과 관련된 설정 -->
	    <property name="javaMailProperties">
		    <props>
<!-- 		     구글 -->
		     <prop key="mail.smtp.auth">true</prop>
      		 <prop key="mail.smtp.starttls.enable">true</prop>
<!--       네이버는 (SSL 필요) -->
<!-- 		      <prop key="mail.smtp.auth">true</prop> -->
<!-- 		      <prop key="mail.smtp.starttls.enable">true</prop> -->
<!-- 		      <prop key="mail.smtps.checkserveridentity">true</prop> -->
<!-- 		      <prop key="mail.smtps.ssl.trust">*</prop> -->
<!-- 		      <prop key="mail.debug">true</prop> -->
<!-- 		      <prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop> -->
		     </props>
	     </property>
	</bean>

 

  • alt+F5로 업데이트 해줄것
  • 내 id는 asdf123@naver.com가 아닌 asdf123만 입력할것
  • port는  작성일 기준 구글은 587 네이버는 465 고정이다 (상단의 코드는 google로 진행)

jsp 페이지

<form action="/sendEmail" method="post">
    <div class="content">
		<div class="radioSelectBox">
			<div class="radioEmailBox">
			<sec:csrfInput />
				<div>
					<span>이메일 주소</span>
					<input type="text" id="member_email" class="inputTextEmail"><span> @naver.com </span>
				</div>
				<div>
					<input type="text" placeholder="인증번호 6자리 입력" maxlength="6" disabled="disabled" id="certNum_ID">
					<button type="button" id="IDmailRequestBtn"><span>인증번호 받기</span></button>
				</div>
				<div>
					<button type="button" id="idCompairBtn">인증번호 확인<span id="mailCheckMsg"></span>
				</div>
			</div>
		</div>
	</div>
	</form>
    
    ㅡㅡㅡㅡajax활용ㅡㅡㅡㅡㅡ
    <script>
var csrfToken = $("input[name='_csrf']").val(); // CSRF 토큰 저장
    //ID인증번호 보내기
    $(document).ready(function() {
        $('#IDmailRequestBtn').click(function() {
            var email = $('#member_email').val();
            $.ajax({
                url: '/survey/sendEmailID',
                type: 'POST',
                headers: {
                    'X-CSRF-TOKEN': csrfToken
                },
                data: {
                    email: email
                },
                success: function(response) {
                    alert('인증번호가 발송되었습니다.');
                    $('#certNum_ID').prop('disabled', false); // 인증번호 입력 필드 활성화

                },
                error: function(xhr, status, error) {
                    alert('유효한 이메일이 아닙니다');
                }
            });
        });
  </script>

 

 


컨트롤러 코드

	@PostMapping("/sendEmailID")
	public ResponseEntity<?> sendIDEmail(@RequestParam("email") String email, HttpSession session) {
		if (memberDAO.memberInfoByEmail(email) != null) {
			// 세션에 인증용 번호 저장
			email = email + "@naver.com";
			int checknum = memberService.sendIDEmail(email);
			session.setAttribute("authCode", checknum);
			return ResponseEntity.ok(checknum);
		} else {
			return null;
		}
	}

 

초기에 void를 사용했으나 정상적으로 작동했음에도 error가 나타났다 이를 찾아보니

AJAX 요청은 응답 본문(return)이 없는 경우 클라이언트 측 JavaScript나 jQuery에서 이를 오류로 해석할 수 있습니다.

즉, return이 null이라 작동되어도 error가 나타났던것이다.

 

ResponseEntity<?> 반환 타입
AJAX 요청의 경우, ResponseEntity를 사용응답 본문(예를 들어, JSON 객체)과 함께 상태 코드를 반환함으로써 클라이언트 측에서 예상하는 응답 형식을 충족시킬 수 있습니다.
ResponseEntity의 경우 return과 동시에 상태코드(200, 300...)를 반환하기에 ajax에서도 이게 실패했는지 아닌지 명확하게 인지할수 있게된다.


서비스 코드

랜덤 난수 생성으로 이를 통한 검증진행

	@Autowired
	JavaMailSenderImpl mailSender;
    
    public int sendIDEmail (String email) {		//난수의 범위 111111 ~ 999999 (6자리 난수)
		Random random = new Random();
		int checkNum = random.nextInt(888888)+111111;
		//이메일 보낼 양식
		String toMail = email;
		String title = "회원가입 인증 이메일 입니다.";
		String content = "인증 코드는 " + checkNum + " 입니다." +
						 "<br>" +
						 "해당 인증 코드를 인증 코드 확인란에 기입하여 주세요.";
		try {
			MimeMessage message = mailSender.createMimeMessage(); //Spring에서 제공하는 mail API
            MimeMessageHelper helper = new MimeMessageHelper(message, true, "utf-8");
            helper.setTo(toMail);
            helper.setSubject(title);
            helper.setText(content, true);
            mailSender.send(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println("랜덤숫자 : " + checkNum);
		return checkNum;
	}

완료 사진

 

참고 링크 

- https://sgdev.tistory.com/12

- https://velog.io/@tjddus0302/Spring-Boot-%EB%A9%94%EC%9D%BC-%EB%B0%9C%EC%86%A1-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0-Gmail

- https://velog.io/@yu_oolong/SpringFramework-%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%9D%B8%EC%A6%9D-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0feat.-%EB%84%A4%EC%9D%B4%EB%B2%84-%EB%A9%94%EC%9D%BC

'Spring' 카테고리의 다른 글

putty를 활용해 EC2에 접근하기  (0) 2024.02.01
Spring MVC의 핵심 애노테이션  (0) 2024.01.26
SSR, CSR, SSG  (0) 2024.01.23
개인 프로젝트 회고  (0) 2024.01.21
인스타 API 연동하기  (0) 2023.08.23

인스타는 api는 주기적으로 업데이트되니 참고할것

해당 포스팅에선 개인 유저의 이미지만 가져오는 방법에 대해 설명합니다.

 

2023-08-24 기준입니다.


초기세팅하기

1. 우측 상단의 앱 만들기 클릭

2.하단의 없음 클릭

3. 앱이름 추가 -> 1번 사진에 보여질 이름을 기입합니다 

4.방금 만들어진 앱을 클릭

5. 좌측 메뉴의 제품 - 제품추가 클릭 (제 사진속 basic display는 이미 추가되었던 상황이라 원래는 제품추가만 있는 상태가 맞습니다)

6. 인스타 baisc display클릭 (그래프 API는 좀더 전문적이며 하단의 링크 참조)
인스타 공식 doc : https://developers.facebook.com/docs/instagram-api

7. 좌측에 생성된 메뉴바를 클릭하여 기본표시 클릭 

8. 해당 화면에서 새 앱 만들기 클릭

9. 하단의 "유효한 OAuth 리디렉션 URI"에 자신이 사용할 URL 입력한뒤 콜백 URL 승인 취소,데이터 삭제 요청 URL도 동일하게 작성하기

(https로 사용하여야 하지만 SSL이 없는 http라도 그냥 https로 적으신뒤 진행해주시면 됩니다)

또한 상단의 id, 코드는 나중에 겹치는 부분이 있기에 

인스타그램 앱 ID - (A)
인스타그램 앱 시크릿코드 - (B) 라고 명명하곘습니다.

10. 화면을 내려서 add or remove instargram testers 클릭

11. 클릭시 해당 화면으로 이동되며 인스타 테스터추가 클릭하여 자신이 가져올 인스타 계정 ID 입력 (대기중으로 뜨면 끝)

12. 가져올 인스타 계정에 로그인한뒤 프로필 -> 우측 상단 톱니모양 클릭 -> 앱 및 웹사이트 -> 테스터 초대 -> 수락클릭

13. 11번째 사진으로 돌아가서 (대기중) 표시가 없어지면 개발자 세팅 완료 

 


단기 토큰 가져오기

인스타 API 링크: https://developers.facebook.com/docs/instagram-basic-display-api

해당 게시글에서 4단계부터 진행한다.
상단의 9번째 사진을 참고할것

1시간 유효합니다

 

1. 기본폼 작성해서 URL에 입력하기 (단기 실행 코드)

코드 수정이 많으니 메모장 또는 여러 사이트를 활용해 바꿀것 (저는 해당 사이트를 활용해서 수정했습니다.)
https://www.mycompiler.io/ko/new/php

단기 실행 코드 발급용 기본 form
https://api.instagram.com/oauth/authorize
  ?client_id={app-id}	//(A)
  &redirect_uri={redirect-uri} // 동일하게 입력한 URL
  &scope=user_profile,user_media	//그대로
  &response_type=code	//그대로

수정한 form
https://api.instagram.com/oauth/authorize
  ?client_id=29..37 
  &redirect_uri=https://localhost:8989/
  &scope=user_profile,user_media
  &response_type=code

만일 문제가 없다면 해당 사진처럼 허용 여부를 물어볼것이다 (띄어쓰기 주의!, 이미 승인한 상황이라 계속 공유할지 물어보는것이다.)

 

2. 허용을 눌러 상단 URL을 복사

설정에 따라 다르겠지만 현재 https에서만 접근을 허용하나 http인 서버를 강제로 https로 입력하여 코드를 얻어낸 모습이다.

이것은 현재 1시간 짜리 단기 코드이며 이를 활용해 장기 사용 토큰으로 변경해야한다.

하단의 코드는 전체 URL이며 여기서 code뒤에 있는 부분만 활용한다 

code 뒤쪽에 보면 #_가 붙는 경우도 있는데 #_는 날리고 사용한다

https://localhost:8989/?code=AQBWc7-au_Y1nh.....BrFQ#_ -> 여기 전체에서
AQBWc7-au_Y1qf1..BrFQ -> 요거만 사용할 예정

 

3. 해당 코드를 활용해 post요청을 전송

리눅스의 경우 cmd에 crul 코드 전송이 가능하지만.. 윈도우는.. 행운을빕니다..

장기 토근 발급 교환코드 기본 form
curl -X POST \
  https://api.instagram.com/oauth/access_token \
  -F client_id={app-id} \ 9번째 사진 (A)
  -F client_secret={app-secret} \ 9번째 사진 (B)
  -F grant_type=authorization_code \ 그대로
  -F redirect_uri={redirect-uri} \ 9번째 사진 URL
  -F code={code} 방금 발급받은 코드 (#_ 지운 코드)
  
  수정한 form
  
curl -X POST \
https://api.instagram.com/oauth/access_token \
-F client_id=29..37 \
-F client_secret=98..6b9 \
-F grant_type=authorization_code \
-F redirect_uri=https://localhost:8989/ \
-F code=AQBWc7-au_Y1nh..JgBrFQ

 

 

정상적으로 돌아갔을경우 상단의 사진과 같은 결과가 출력된다 (해당 코드 장기토큰에서 사용할 예정이니 저장해두기)

IGQWRO....3VE9ndwZDZD", "user_id": 650...15

 

4. 정상적으로 받아왔는지 테스트하기

curl -X GET \
  'https://graph.instagram.com/{user-id}?fields=id,username&access_token={access-token}'
  여기에서 방금 받아온 id, 토큰값을 변경하기
curl -X GET \
'https://graph.instagram.com/650...15?fields=id,username&access_token=IGQWRO....3VE9ndwZDZD

자신이 가져오기로한 계정 이름이 username과 동일한지 확인해보자

여기까지 진행한걸 축하한다 드디어 인스타 1시간짜리 연결이 완성되었다.

현재까지 진행한건 단기 토큰으로 이를 장시간 사용하기 위해선 장기토큰으로 바꿔줘야한다.


장기 토큰 가져오기

 

만일 토큰 기간이 다되었단 에러가 나타날경우 바로 위의 단기 토큰 가져오기를 다시 진행해주시면 됩니다

(1시간 이내로 작업하기)

 

장기 토큰 가져오기 기본 form
curl -i -X GET "https://graph.instagram.com/access_token
  ?grant_type=ig_exchange_token	//그대로
  &client_secret={instagram-app-secret}	// (B)
  &access_token={short-lived-access-token}"	//방금 발급받은 1시간짜리 토큰값
  
작성 예시 (해당 코드는 가독성을 위해 이렇게 작성되었지만 crul에서 가끔 못읽는 경우도 있으니 1줄로 보내주자!..)
curl -i -X GET "https://graph.instagram.com/access_token
?grant_type=ig_exchange_token
&client_secret=98..b9
&access_token=IGQW...ZDZD"

즉, 이렇게 입력해줘라
curl -i -X GET "https://graph.instagram.com/access_token?grant_type=ig_exchange_token&client_secret=98..b9&access_token=IGQW...ZDZD"

완료시 cmd에선 다음과 같이 출력되며 expires_in은 sec로 약 60일간 유효한 토큰을 얻은것이다.

만일 해당 토큰이 만료될경우 다음과 같은 방법을 사용한다.


장기토큰 재발급 받기

고맙게도 이건 쉽다.

장기 실행토큰 새로 고침 기본 form
curl -i -X GET "https://graph.instagram.com/refresh_access_token
  ?grant_type=ig_refresh_token	//그대로
  &access_token={long-lived-access-token}"	//60일짜리 토큰
  
  적용한 form(이거도 1줄로 써주자)
curl -i -X GET "https://graph.instagram.com/refresh_access_token
?grant_type=ig_refresh_token
&access_token=IGQWROUFAwcT...BQQZDZD"

여기까지 문제없이 따라왔다면 마지막으로 검색해보며 포스팅을 끝내겠다

URL 기본 form
https://graph.instagram.com/{app-id}/media?fields=id,media_type,media_url,permalink,thumbnail_url,username,caption&access_token={access_token}
{app-id}는 (A)를, access_token은 아까 발급받은 1시간, 60일 짜리 토큰 아무거나 사용하면 된다.

적용 form
https://graph.instagram.com/65..15/media?fields=id,media_type,media_url,permalink,thumbnail_url,username,caption&access_token=IGQWRQV...QZDZD

해당 url을 입력할경우 json 형태로 자신이 원하는 인스타 데이터를 가져올수 있게된다!

 

참고사이트 (php코드 변경) : https://www.mycompiler.io/ko/new/php

참고 블로그 : https://tonhnegod.tistory.com/245

'Spring' 카테고리의 다른 글

putty를 활용해 EC2에 접근하기  (0) 2024.02.01
Spring MVC의 핵심 애노테이션  (0) 2024.01.26
SSR, CSR, SSG  (0) 2024.01.23
개인 프로젝트 회고  (0) 2024.01.21
SMTP를 활용하여 이메일 보내기  (0) 2024.01.04

IP(Internet Protocol)

가상의 인터넷 환경에서 메세지를 주고받기 위해선 상호간의 위치를 지정할수 있는 주소가 필요한데 이를 IP주소라고 칭한다.

초기의 인터넷 환경이 작았을땐 다이렉트로 연결하면 무방했지만 점차 웹은 더 넓은 영역을 갖게되었고 이를 보완하고자 나타난것이 IP 프로토콜이다.

IP는 지정한 주소에 데이터를 전달 및 패킷이란 단위로 데이터를 전달한다.(출발 및 목적지 IP, 기타 정보로 통상적으로 1500byte로 전달)



IP프로토콜의 한계

1. 비연결성(Connectionless)

  • 클라이언트와 서버가 한번 연결을 맺은후 서버가 응답을 마치면 연결을 끊는것(쉽게 말해 줄서있던사람이 용건이 끝나면 보내되 추가적인 용건이 생긴다면 줄 맨뒤로 보내버리는것) -> 그때마다 핸드쉐이킹을 진행해야 하기에 오버헤드가 발생할 여지가 있다.
  • 만일 연결을 유지할경우 서버는 이를 위해 지속적인 자원을 할애해야하며 이는 곧 서버의 효율저하를 초래한다. (서버 자원의 효율화)
  • 오버헤드를 줄이기 위해서 HTTP의 KeepAlive속성을 사용할수 있다 (일정 시간동안 서버-클라이언트간 패킷 교환이 없을경우 상대방에게 패킷을 주기적으로 보내며 이에 대한 응답이 없을경우 연결을 끊어버리는것 )
  • 요청을 받을경우 상대의 상태가 어떻든(꺼져있거나 주소가 다르거나 하여도) 일단 보내고 연결을 끊어버리기에 의도한 순서나 결과에 맞지 않는 결과가 출력된다.

2. 비신뢰성

  • 중간에 패킷이 사라지거나(패킷소실), 패킷의 순서가 다를경우(1500Byte가 초과될경우 패킷을 분할하여 보내나 모두가 동일한 경로로 가지 않기 때문에 순서가 다르게 도착할 우려가있다.)

3. 프로그램 구분 불가능

  • 동일한 IP를 사용하는 서버에서 통신하는 애플리케이션이 2개 이상일경우 어떤 애플리케이션으로 전달해야할지 구분이 어렵다 

이러한 문제는 후술할 TCP/UDP를 통하여 해결하였다.

 

오버헤드 -  어떤 처리를 하기위해 들어가는 간접적인 처리시간


TCP/UDP

Transmission Control Protocol (TCP) - 전송 제어 프로토콜

  • 데이터를 보내는데 연결이 필요하다. ->핸드쉐이크를 통한 목적지 상태를 점검 (IP프로토콜 3번)
  • 자료가 스트림 형태로 전송되며 타 컴퓨터에서 수신되어 링크가 생성되는 연결기반이다. 
  • 3way-hanshake를 통한 작업이 많기에 신뢰성, 연결성이 보장되나 속도가 떨어진다 (실질적인 데이터 전송이 이뤄지기전 진행하는 과정으로 목적지의 상태가 멀쩡한지 확인하는 과정이 추가된다. -> IP프로토콜 1번 해결)
  • 데이터 전달 보증 - 패킷소실이 일어나도 클라이언트가 해당 사실을 인지할수 있도록 알려준다(Sequence number 참조) -> IP프로토콜 2번 해결
  • 가상회선 방식 - 데이터 전송전 논리적인 연결이 설정되는데 각 패킷마다 가상회선 식별번호(VCI, Virtual Circuit Identifier)가 포함되어 모든 패킷이 전송되면 가상회선이 사라지고 패킷들은 전송된 순서대로 도착한다. (하단의 Acknowledgment Number 참조)
  • 서버에서 내부적으로 최적화가 가능하지만 서버 자원측면에서 안좋기에 가급적 클라이언트에 재요청하는 방식

TCP 헤더의 모습

 

Source port - 출발지의 포트 번호

Destination Port - 목적지 포트번호

Sequence number -  바이트 단위로 순서화되는 번호로 TCP 세그먼트 첫번째 byte에 부여되며 이를통해 3way handshake가 이뤄지고 흐름제어 기능을 제공한다 -> 데이터 첫 번째 비트에 할당되는 임의의 32비트, 한번의 연결에서 한번만 사용되며 동일한 연결에서 다른 데이터 전송을 위해 다른 시퀀스 번호를 사용해야한다.

Acknowledgment Number(확인번호) - 수신을 기다리는 다음 byte번호 (마지막으로 수신에 성공한 번호의 +1)

Reserved - 에약된 필드 (현재는 미사용)

Window - 자신의 수신 버퍼 여유용량 크기를 통보하여 얼만큼의 데이터를 받을수 있는지 보여줌

Offset - 헤더 길이 필드이며 Ipv4와 동일하게 /4를 진행한후 2진수로 작성됨

Urgent Pointer - 어디서부터 긴급값인지 알려주는 플래그 (TCP Flags의 U와 세트!)

TCP Flags

  • U (Urgent, 긴급비트) - 내가 지금 보내는 데이터의 우선순위가 높음 (Urgent Pointer과 세트)
  • S (SYN 비트, 동기화비트) - 동기화 비트, 상대방과 연결을 시작할떄 사용되는 플래그 (핸드쉐이크에 사용)
  • A (ACK 비트, 승인 비트) 요청에 대한 응답을 진행할때 사용되는 플래그 (핸드쉐이크에 사용)
  • P (Push 비트) - Tcp 버퍼가 일정한 크기만큼 쌓여야 넘기는데 이에 상관없이 계속 데이터를 밀어넣겠다 (유튜브 버퍼링)
  • R (Reset 비트) -  초기화 비트, 연결된 상태에서 어떤 문제가 발생했을때 연결을 리셋하게됨
  • F (Fin비트, 종료비트)

 

User Datagram Protocol (UDP)

  • 비연결성 - 데이터를 보내는데 연결이 필요하지 않다. -> 핸드쉐이크를 통한 연결상태 점검과정을 생락하고 일방적으로 보냄
  • UDP의 경우 단순하게 테이터만 보내기 때문에 신뢰성을 보장하지 않으나 가볍고 속도가 빠르다 -> 데이터를 효율적으로 보내야하는 응용프로그램, 게임은 직접적인 기능떄문에 UDP를 사용한다.
  • IP와 비슷하되 Port와 체크섬이 추가된다
  • 데이터그램 방식 - 데이터 전송 전에 송/수신자 사이에 가상 회선 (논리적 경로)를 설정하지 않고, 패킷들이 각기 독립적으로 전송되는 방식 -> 이로인해 전송되는 순서가 바뀔 여지가 있다.

체크섬 - 중복검사의 일종으로 송신된 자료의 무결성을 보호하는 방법이다. 주로 해쉬값 비교를 통해 이뤄지며 

 

 


3way handshake 연결과정

1. SYN 요청 (클라이언트 -> 서버) -> 클라이언트가 서버에 연결 요청을 하기위해 SYN 데이터를 보낸다

  • SYN -1, ACK - 0
  • 해당 과정에서 window크기, 최대 세그먼트 크기 등 정보를 같이 보낸다 (window가 2000비트, 최대 세그먼트 크기가 200비트인경우 최대 10개의 세그먼트가 전송된다)

2. SYN + ACK (서버 -> 클라이언트) -> 요청을 받은 서버는 접속요청에 응답하기 위해 (SYN + ACK) 데이터를 보낸다. 해당 포트상태

  • 서버측 클라이언트는 SYN, ACK로 응답한다
  • ACK는 여기에 window크기, 최대 세그먼트 크기 등 정보를 같이 보낸다 -> window가 2000비트, 최대 세그먼트 크기가 200비트인경우 최대 10개의 세그먼트가 전송된다
  • SYN에서 사용되는 시퀀스 번호와 클라이언트의 SYN과 다르며 서버는 자신의 window와 최대 세그먼트 크기를 클라이언트에 전달한다. (ACK의 승인번호는 수신된 시퀀스 번호보다 1만큼 크다)
  • ACK - 1, SYN - 1 (SYN이 1인 이유는 자신도 정상적으로 받았음을 의미하면 동시에 ACK를 1로 바꿔 응답할 준비가 되었음을 알림)

3. ACK (클라이언트 -> 서버) -> 서버의 승인이 떨어졌으니 자신이 필요로 하는 데이터를 보낸다.

  • SYN에서 사용되는 시퀀스 번호와 클라이언트의 SYN과 다르며 서버는 window와 최대 세그먼트 크기를 클라이언트에 전달한다. (ACK의 승인번호는 수신된 시퀀스 번호보다 1만큼 크다)
  • ACK - 1, SYN - 0 (연결이 완료되었기에 SYN은 0으로 바꿔버리고 연결간 데이터 전송을 위해 ACK는 1 유지)

 

3way handshake 종료과정

 

1. FIN (클라이언트 -> 서버) -> 사용이 끝났으니 종료할거라 플래그를 보냄.

  • 임의의 시퀀스 번호로 메시지를 서버로 전달
  • FIN - 1, ACK - 0 (FIN은 끝임을 알리기 위해 1로 변경, 연결을 끊기 위해 ACK는 0으로 변경)

2. ACK + FIN (서버 -> 클라이언트) -> FIN에 대한 응답을 잘 수신했고 나도 끊기위해 FIN 플래그를 보냄

  • SYN에서 사용되는 시퀀스 번호와 클라이언트의 SYN과 다르며 서버는 window와 최대 세그먼트 크기를 클라이언트에 전달한다. (ACK의 승인번호는 수신된 시퀀스 번호보다 1만큼 크다)
  • 서버는 클라이언트의 플래그를 FIN - 1, ACK - 1 (ACK는 클라이언트가 보낸 FIN을 정상적으로 받았음을 알리기 위해 1로 변환, FIN은 서버도 클라이언트와 끊음을 알리기 위해 1로 변환)
  • 해당 과정이 끝날경우 클라이언트에서 서버측 연결은 종료된다

3. ACK (클라이언트 -> 서버) -> 연결 정지에 대한 서버의 승인이 떨어졌으니 윗단계에서 끊고 동시에 정상적으로 종료됨을 알리는 데이터를 보낸다.

  • 클라이언트는 FIN을 수신후 ACK 플래그 1 설정, 서버의 FIN 시퀀스 번호보다 1만큼 큰 승인버호를 클라이언트로 보낸다 (진짜 끝낸다고 요청을 보내면서 클라이언트의 FIN플래그도 0으로 바꾼다)


상단의 이론을 진행하며 IP가 어떤식으로 소통하는지 확인하였다.
그렇다면 우리는 실질적으로 100.100.100.1이 아닌 naver.com과 같은 형태로 진행되는데 이에 대해서도 설명하겠다.


DNS(Domain Name System)

 

IP만 알면 되는데 DNS를 사용하는 이유 - IP는 기억하기 어렵고 IP는 변경될 우려가 있다

  • 서버에서 망 사용료를 연체하여 해지됬으나 이후 다시 IP를 개설하여도 이 사실을 모르는 사람들은 대다수가 기존의 사이트로 돌아오지 못할것이다.
  • google에 접속하려고 할때 200.200.200.2라고 할경우 이것이 어떤 사이트인지 구분이 어렵고 google과 연관된 사이트라고 해도 IP를 다른곳에서 가져가버릴경우 200.200.123.4.. 220.324.123.2.. 이런식으로 연결해놔야 하기에 굉장히 불편하다.

그리하여 DNS라는 시스템을 고안하였으며 단순한 도메인명(google.com)만 입력할경우 이에 알맞는 IP로 찾아가게 되는것이다.

 

 

URL, URN, URI

URI (Uniform Resource Identifier) - 통합 자원 식별자를 의미한다.

  • 인터넷에 있는 자원을 나타내는 유일한 주소를 의미하며 쉽게 말해서 URN + URL 두개를 합친 상위의 개념이다.

URN (Uniform Resource Name) 

  • URI의 표준 포맷중 하나로 이름으로 리소스를 특정하는 URI이다.
  • URN은 리소스를 영구적이며 유일하게 식별이 가능한 URI다.
  • 실제 자원을 찾기 위해선 URN을 URL로 변환해 이용한다.
  • 리소스에 어떻게 접근할지 명시하지 않고 경로와 리소스 자체를 특정하는것 -> 크롬에 PDF 파일 같은걸 던져보면 알것이다. (file://0.0.0.123/)

URL (Uniform Resource Locator)

  • 네트워크 상에서 웹페이지 ,이미지, 동영상등 파일이 위치한 정보를 나타낸다.
  • 어떻게 리소스를 얻고 어디서 가져올지 명시
  • www.google.com

HTTP의 역사

HTTP/0.9 - GET 메서드만 지원, HTTP 헤더X

HTTP/1.0 - 메서드(post,get,delete...), 헤더, 상태코드(200,300...) 추가

  • 요청헤더 - http 버전이 생김
  • 응답헤더 - 상태코드와 content-type이 생겨 html파일 외의 다른 타입의 파일도 전송가능
  • 단기 커넥션 - connection 하나당 1개의 요청, 1개의 응답만 처리가능 -> 상단의 비연결성과 비슷한 맥락 

HTTP/1.1 - 가장 범용적으로 사용됨

  • Persistent connection - 지정된 timeout 동안 연속적인 요청 사이에 커넥션을 닫지 않음 -> 비 연결성에 약간의 여유를 주었다
  • Pipelining - 커넥션에서 응답을 기다리지 않고 순차적으로 여러 요청을 연속적으로 보내 그 순서에 맞춰 응답받아 지연시간을 줄이는 방식 -> Head of Line Blocking같은 문제점이 많아 사장됨.
  • Head of Line Blocking - 우선순위로 들어온 응답시간이 길어질경우 그 뒤에 있는 응답시간도 길어진다.

HTTP/2.0 - HTTP 1.1 성능개선 + 확장

  • 메시지 전송방식의 변화 : 바이너리 프레이밍 계층 사용
  • 파싱, 전송속도 증가
  • 오류 발생 가능성 저하
  • 멀티플랙싱
  • HPACK 압축 - 헤더 중복값 개선

HTTP/3.0 - TCP대신 UDP를 이용한 QuIC 프로토콜 사용

  • 3.0 미만은 전부 TCP 프로토콜을 활용했으나 해당 버전부턴 UDP를 사용

 

클라이언트와 서버를 구분해야 하는 이유 -> 각자의 역할에 집중(독립적인 발전) 가능하기 때문이다.

  • 리퀘스트, 리스폰 구조로 클라이언트는 서버에 요청을 보내고 응답을 대기하다 메시지가 오면 확인만 하면 된다
  • 이것은 곧 서로 독립성을 의미하며 단적인 예시로 서버가 방금까지 JAVA를 쓰다 C로 넘어가도 클라이언트는 이것과 상관없이 그냥 요청만 하면 서버에선 이를 확인하고 보내줄수 있다
  • 서버에선 비즈니스 로직 및 서비스만 구현하고 만일 문제가 발생할경우 클라이언트는 문제가 고쳐지기 전까지 다른작업을 진행하다 추후 완료되었을때 다시 접속만 하면 된다.

 

'CS' 카테고리의 다른 글

JS파일 가져오기 로컬, 원격 차이  (0) 2024.08.03
크로스 도메인,SOP, CORS, XSS,  (0) 2024.01.25
HTTP 헤더  (0) 2023.05.06
난독화  (0) 2023.05.03
개발방법론  (0) 2023.05.02

+ Recent posts