Queue, HTTP

calis_ws·2023년 6월 19일
0

Queue

FIFO(First-In-First-Out) 선입선출의 원칙을 따르며, 데이터의 순서를 유지하고, 삽입과 삭제가 빠르게 이루어지는 특징을 갖고 있다.

ex) 줄을 서는 상황이나 작업 처리, 이벤트 처리 등

새로운 요소는 큐의 끝(rear)에 추가되고, 요소를 제거할 때는 큐의 맨 앞(front)에서 제거된다.

선형 Queue

package queue;

public class MyQueue {
    private final int[] arr = new int[4];
    // Queue에서 데이터 꺼내는 위치
    private int front = -1;
    // Queue에서 데이터 추가하는 위치
    private int rear = -1;

    public MyQueue() {}

    // 데이터 추가
    public void enQueue(int x) {
        // rear + 1이 배열의 크기만해질 때
        if (rear == arr.length - 1) {
            throw new RuntimeException("queue is full");
        }
        // rear를 하나 증가시킨다.
        rear++;
        // arr[rear]에 data를 할당한다.
        arr[rear] = x;
    }

    // 데이터 회수
    public int deQueue() {
        // front == rear일때 큐가 비어있음
        if (front == rear) {
            throw new RuntimeException("queue is empty");
        }
        // front를 하나 증가시킨다.
        front++;
        // arr[front]의 값을 반환한다.
        return arr[front];
    }

    // 큐가 비어있는지 확인
    public boolean isEmpty() {
        return front == rear;
    }

    // 다음에 나올 데이터가 무엇인지 확인 (Queue에서 빼내지 않음)
    public int peek() {
        if (isEmpty()) {
            throw new RuntimeException("queue is empty");
        }
        // 비어있지 않다면 front + 1의 값 반환
        return arr[front + 1];
    }

    public static void main(String[] args) {
        MyQueue intQueue = new MyQueue();
        intQueue.enQueue(1);
        intQueue.enQueue(2);
        intQueue.enQueue(3);
        System.out.println(intQueue.deQueue());
        System.out.println(intQueue.deQueue());
        System.out.println(intQueue.deQueue());

        intQueue.enQueue(4);
        System.out.println(intQueue.deQueue());

        intQueue.enQueue(5);
        intQueue.enQueue(6);
    }
}
  • 선형 Queue의 문제점은 배열의 크기가 제한적이고 그로 인해 메모리 공간이 낭비된다.

원형 Queue

배열의 끝에 도달하면 다시 배열의 처음으로 돌아가기 때문에 요소를 순환하며 추가 및 제거하는 순환구조

선형 Queue에 비교해서 가장 큰 특징은 메모리 사용이 더 효율적이다.

package queue;

public class MyCycQueue {
    private final int size = 4;
    private final int offset = size + 1;
    private final int[] arr = new int[offset];
    private int front = 0;
    private int rear = 0;

    public MyCycQueue() {}

    // 데이터 추가
    public void enQueue(int x) {
        // 다음에 데이터가 들어가는 곳 : (rear + 1) % (offset)
        // 다음에 데이터가 나올 곳과 일치 할 경우 Full
        if ((rear + 1) % offset == front) {
            throw new RuntimeException("queue is full");
        }
        rear = (rear + 1) % offset;
        arr[rear] = x;
    }

    // 데이터 회수
    public int deQueue() {
        if (front == rear) {
            throw new RuntimeException("queue is empty");
        }

        front = (front + 1) % offset;
        return arr[front];
    }

    public boolean isEmpty() {
        return front == rear;
    }

    public static void main(String[] args) {
        MyCycQueue queue = new MyCycQueue();
        queue.enQueue(1);
        queue.enQueue(2);
        queue.enQueue(3);
        queue.enQueue(4);
        System.out.println(queue.deQueue());
        queue.enQueue(5);
    }
}

interface Queue<T>

Java Collection 프레임워크에서 기본 제공하는 인터페이스이다.

package queue;

import java.util.LinkedList;
import java.util.Queue;

public class JavaQueue {
    public static void main(String[] args) {
        Queue<Integer> queue = new LinkedList<>();
        // enqueue
        // offer, add - enQueue에 해당하는 메소드
        // Queue가 가득 차 있다면,
        // offer - false를 반환, add - 예외 발생
        queue.offer(1);
        queue.add(2);

        // dequeue
        // remove, poll - deQueue에 해당하는 메소드
        // Queue가 비어있다면
        // poll - null을 반환, remove - 예외 발생
        System.out.println(queue.remove());
        System.out.println(queue.poll());

        // peek
        // element, peek - peek에 해당하는 메소드
        // Queue가 비어있다면
        // peek - null을 반환, element - 예외 발생
        System.out.println(queue.peek());
        System.out.println(queue.element());
    }
}

HTTP

HTML 문서와 같은 자원을 주고받는 방식 (HyperText Transfer Protocol)

  • 통신계층 이후 전달된 데이터가 어떻게 표현되어 있는지 나타냄

  • 클라이언트와 서버가 통신할때 주고받는 문서의 양식 같은 것

  • Client - server protocol 이라고도 부른다

HTTP Request

Request Line

HTTP Method, URL 경로, HTTP 버전

Request Headers

요청에 대한 부수적인 정보

어떤 방식으로 해석해야 하는지

어떤 형태의 응답을 기대하는지

Request Body

요청을 통해 전달하고 싶은 실제 데이터

상황에 따라 (조회 요청 등) 생략 가능

HTTP Request Methods (CRUD)

  • GET – 데이터 조회를 목적으로 하는 요청

  • POST – 데이터를 포함한 요청을 보낼 때 (CREATE)

  • PUT – 데이터를 포함한 요청을 보낼 때 (UPDATE)

  • DELETE – 데이터를 삭제하는 요청을 보낼 때

HTTP Response

Status Line

HTTP 버전, 상태 코드, 상태 코드 메시지

Response Headers

응답에 대한 부수적인 정보

어떤 방식으로 해석해야 하는지 등

Response Body

요청을 통해 전달하고 싶은 실제 데이터

HTTP Status Codes

HTTP 요청의 처리가 어떻게 되었는지 알려주는 상태 코드

  • 100 ~ 199 : 정보 제공 목적 (개발자가 사용하지 않고, 컴퓨터 사이에 사용)

  • 200 ~ 299 : 요청이 성공적으로 처리되었음

  • 300 ~ 399 : 요청의 처리를 위해 클라이언트의 추가적인 행동이 필요 (redirect)

  • 400 ~ 499 : 클라이언트가 처리가 불가능한 요청을 한 경우 (400, 401, 403, 404)

  • 500 ~ 599 : 서버에 문제가 생겨서 처리가 불가능해진 경우 (500)

Postman

  • Postman은 개발한 API를 테스트하고, 테스트 결과를 공유하여 API 개발의 생산성을 높여주는 플랫폼이다.

  • http 요청을 보내고 응답을 보여준다.

http 프로젝트 생성

Postman header-all

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
HELLO HTTP
</body>
</html>

MappingController

package com.example.http;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Slf4j  // log 변수 만들어줌
@Controller
public class MappingController {
//    private static final Logger logger = LoggerFactory.getLogger(MappingController.class);

    // '/path'로 오는 GET 요청에 대해서 메소드를 실행하고 싶을 때
    @RequestMapping(value = "/path", method = RequestMethod.GET)
    public String getPath() {
        log.info("GET /path");
        return "index";
    }

    // '/path'로 오는 POST 요청에 대해서 메소드를 실행하고 싶을 때
    @RequestMapping(value = "/path", method = RequestMethod.POST)
    public String postPath() {
        log.info("POST /path");
        return "index";
    }

    // '/path'로 오는 PUT 또는 DELETE 요청에 대해서
    // 메소드를 실행하고 싶을 때
    @RequestMapping(value = "/path", method = { RequestMethod.PUT, RequestMethod.DELETE })
    public String putOrDeletePath() {
        log.info("PUT or DELETE /path");
        return "index";
    }

    // '/path'로 오는 POST 요청이면서 JSON 데이터를 포함하는 요청에 대하여
    // 메소드를 실행하고 싶을 때
    @RequestMapping(value = "/path", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
    public String consumes() {
        log.info("POST /path Content-Type: application/json");
        return "index";
    }

    // '/path'로 오는 POST 요청이면서
    // 헤더에 x-likelion 이라는 헤더가 값이 hello로 지정되어 있을 때
    // 메소드를 실행하고 싶을 때
    @RequestMapping(value = "/path", method = RequestMethod.POST, headers = "x-likelion=hello")
    public String headerWith() {
        log.info("POST /path with x-likelion=hello");
        return "index";
    }

    // '/path'로 오는 POST 요청이면서
    // Query Parameter로 likelion이 hello로 할당되어 있을 때
    // 메소드를 실행하고 싶을 때
    @RequestMapping(value = "/path", method = RequestMethod.POST, params = "likelion=hello")
    public String params() {
        log.info("POST /path with parameter likelion");
        return "index";
    }
}

HeaderController

package com.example.http;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;

import java.util.List;
import java.util.Map;

@Slf4j
@Controller
public class HeaderController {
    // 'header-one' 으로 들어온 HTTP 요청에 대하여
    // 헤더 중 'x-likelion' 이라는 헤더의 값을 인자로 전달받고 싶을 때
    @PostMapping("/header-one")
    public String getHeader(@RequestHeader("x-likelion") String header) {
        log.info("POST /header-one header: " + header);
        return "index";
    }

    @PostMapping("/header-optional")
    public String getHeaderOptional(@RequestHeader(value = "x-likelion", required = false) String header) {
        log.info("POST /header-optional header: " + header);
        return "index";
    }

    @PostMapping("/header-type")
    public String getHeaderInteger(@RequestHeader(value = "x-likelion-int") Integer header) {
        log.info("POST /header-type header: " + header);
        return "index";
    }

    @PostMapping("/header-all")
    public String getHeaderAll(
//            @RequestHeader // 모든 헤더를 다 가져올 때
//            Map<String, String> headerMap) {

            @RequestHeader // 모든 헤더를 다 가져올 때
            MultiValueMap<String, String> headerMap
    ) {
        log.info("POST /header-all");
        for (Map.Entry<String, List<String>> entry : headerMap.entrySet()) {
            log.info(String.format("%s: %s", entry.getKey(), entry.getValue()));
        }
        return "index";
    }
}

Postman Body JSON

BodyController

package com.example.http;

import com.example.http.dto.ArticleDto;
import com.example.http.dto.ResponseDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

@Slf4j
@Controller
public class BodyController {
    // '/body' 로 요청이 들어왔을 때,
    // ResponseDto 데이터를 표현한 JSON 응답을 반환하는 메소드
    @PostMapping("/body")
    public @ResponseBody ResponseDto body(@RequestBody ArticleDto requestDto) {
        log.info(requestDto.toString());
        ResponseDto response = new ResponseDto();
        response.setStatus(200);
        response.setMessage("success");
        return response;
    }
}

ArticleDto

package com.example.http.dto;

import lombok.Data;

// 블로그 게시글
// 게시글 - 제목
// 게시글 - 내용
/*
{
    "title": "제목",
    "content": "content"
}
 */
@Data
public class ArticleDto {
    private String title;
    private String content;
}

ResponseDto

package com.example.http.dto;

import lombok.Data;

// 일반적인 응답
// 상태
// 메시지
/*
{
    "status": 200,
    "message": "success"
}
 */
@Data
public class ResponseDto {
    private Integer status;
    private String message;
}

인사이트 타임

점의 위치 구하기

https://school.programmers.co.kr/learn/courses/30/lessons/120841

class Solution {
    public int solution(int[] dot) {
        if (dot[0] > 0 && dot[1] > 0) return 1;
        else if (dot[0] < 0 && dot[1] > 0) return 2;
        else if (dot[0] < 0 && dot[1] < 0) return 3;
        else return 4;
    }
}

카운트 업

https://school.programmers.co.kr/learn/courses/30/lessons/181920

class Solution {
    public int[] solution(int start, int end) {
        int[] answer = new int[end - start + 1];
        for (int j = start; j <= end; j++) {
            for (int i = 0; i < answer.length; i++) {
                 answer[i] = j++;
            }
        }
        return answer;
    }
}

문자열 정수의 합

https://school.programmers.co.kr/learn/courses/30/lessons/181849

class Solution {
    public int solution(String num_str) {
        int answer = 0;
        for (int i = 0; i < num_str.length(); i++) {
            answer += Integer.parseInt(num_str.substring(i, i + 1));
        }					// (0, 1)이면 idx 0부터 1 시작 전까지
        return answer;
    }
}

처음에 while 문으로 풀었는데 런타임 에러가 와다다 뜨길래 실패.
이유는

역시 갓원기

그래서 substring으로 잘라서 더했다. (구글링한건 비밀)

review

Stack에 이어서 이번 알고리즘 시간에는 Queue에 대해 배워보았다. 하지만 Stack도 쉽지 않았던 만큼 Queue도 완전하게 이해하진 못했다. 역시 알고리즘은 언제나 골치 아프게 만든다. 선입선출이란 것만 기억에 남네

오후에는 http에 대해서 배웠는데 늘 하던 스프링과 비슷해서 나쁘진 않았다. 역시 완벽히 이해하진 못했지만. 매주 월요일은 강사님께서 수강생들을 위해, 그리고 본인을 위해(?) 어렵지 않게 진도를 나가시는 것 같다. 이 점은 아주 만족한다. 오늘 맛보기로 배웠던 Body 컨트롤러를 내일 마저 완성할 것 같다. 이번 주도 힘내보자.

profile
반갑습니다람지

0개의 댓글