728x90
반응형

AutoScaling 서비스란?

서버 그룹 모니터링 결과나 사용자가 미리 정한 일정에 따라 가상 서버 수를 자동으로 증가 또는 감소시켜서 수요 변화에 탄력적으로 대응할 수 있게 해 주는 서비스

 

AutoScaling 설정 항목

  1. Launch Configuration 현황 : Auto Scaling Group과 현재 설정되어 있는 Launch Configuration을 확인할 수 있으며, Launch Configuration을 변경할 수 있습니다.
  2. Scaling 정책 설정 현황 : 모니터링 이벤트가 발생하면 Scaling 정책에 따라 가상 서버를 생성 또는 반납할 수 있습니다. Scaling 정책을 설정할 수 있으며, 증감변경/비율변경/고정값 중에서 선택 가능합니다.생성된 Scaling에 대해 수정, 삭제, 실행이 가능합니다. (모니터링 이벤트 설정은 Cloud Insight 사용가이드의내용을 참조하여 설정하세요)
  3. 일정 설정 현황 : 고객이 미리 지정한 시간에 가상 서버를 생성 또는 반납할 수 있습니다. 최소 용량/최대 용량/기대 용량 등 Scaling 정책 및 스케줄을 설정할 수 있습니다. 생성한 스케줄에 대해 수정 및 삭제도 가능합니다.
  4. 이력 확인 : Auto Scaling 실행 이력을 상세하게 확인할 수 있습니다.
  5. 통보 설정 : Auto Scaling을 통해 이벤트 발생 시 통보대상자 및 통보 방법(메일/SMS)을 설정할 수 있습니다.
  6. 서버 목록 확인: Auto Scaling Group에 소속된 서버 리스트를 확인할 수 있습니다.
  7. 프로세스 관리 : Auto Scaling Group의 프로세스 상태를 확인하고 변경할 수 있습니다. 일시 정지 및 재시작을 수행할 수 있습니다.

AutoScaling 서비스 환경 제한 사항

  • 총 디스크 사이즈 150GB 이하 서버만 가능
  • Windows OS는 Windows 2012. 2016만 지원
  • Micro 서버는 불가
  • High Memory 서버는 불가(추후 개선 예정)
  • Local disk 기반 서버는 불가

AutoScaling 설정 제한 사항

  • 고객별 생성 가능한 Auto Scaling Group 최대 수: 100
  • 고객별 생성 가능한 Launch Configuration 최대 수: 100
  • Auto Scaling Group당 생성 가능한 스케줄(Scheduled Action) 최대 수: 100
  • Auto Scaling Group당 생성 가능한 최대 서버 수: 30대
  • Auto Scaling Group당 생성 가능한 Scaling Policy 최대 수: 10
  • Auto Scaling Group당 연결 가능한 Load Balancer 최대 수 : 10

 

관리용 보류(administrative suspension)

- 해당 Launch Configuration에 결함이 있는 것으로 확정하고 더 이상 그 Launch Configuration으로부터 서버를 생성하지 않도록 서버 인스턴스 생성 및 서비스 적용 프로세스를 보류

 

Launch Configuration

Auto Scaling Group에서 가상 서버를 시작 구성하는 데 사용하는 템플릿
- Auto Scaling Group을 생성할 때는 Launch Configuration 지정

 

쿨다운

- Default Cooldown(초) 새로운 서버가 생성되었다고 해도 Init-Script 실행, 업데이트 설치 등의 이유로 실제 서비스를 수행할 수 있을 정도로 준비되기까지는 시간이 소요될 수 있음
- 쿨다운(Cooldown) 시간이란 실제 Scaling이 수행 중이거나 수행 완료된 이후에 모니터링 이벤트 알람이 발생하더라도 무시하도록 설정한 기간

 

헬스체크

Auto Scaling Group의 가상 서버에 주기적인 상태 확인을 수행하여 상태가 비정상인 가상 서버를 식별하도록 Health Check를 진행함

 

반납 정책

- Auto Scaling 과정에서 추가된 서버에 대한 Scale-in 작업에 대해 고객이 API 질의 형식으로먼저 반납할 서버 지정 가능
- 기본 설정은 먼저 생성된 서버부터 반납

 

Launch Configuration 설정

  1. 콘솔 접속하기
  2. 서버 이미지 선택하기
  3. 서버 설정 - 요금제는 시간제로 적용, Init-Script는 선택사항
  4. 이름 설정
  5. 인증키 설정
  6. 최종 설정

AutoScaling 설정

  1. Launch Configuration 선택하기
  2. 그룹 설정하기 - 기대 용량, 상세 모니터링, 쿨다운 기본값, 헬스 체크 보류기간, 헬스 체크 유형
  3. 네트워크 접근 설정하기
  4. 일정 설정하기 - Time Zone을 KST, UTC중에 선택함.  증감변경, 비율변경, 고정값 중 선택하고 scaling 설정으로 비율변경을 선택할 경우 최소 조정 폭을 지정 
  5. 통보 설정하기 - 통보 방법을 SMSEmail 중 원하는 방법으로 지정
  6. 최종 확인하기
728x90
반응형

'Server > Naver Cloud' 카테고리의 다른 글

Naver Cloud | Networking | VPC, Load Balancer  (0) 2022.09.26
Naver Cloud | Compute | VPC  (0) 2022.09.21
728x90
반응형

VPC

네이버 클라우드에서 계정당 최대 3개 만들 수 있다.

SSD 서버

표준 서버보다 10~20배 이상의 고성능 I/O를 제공하는 SSD 서버를 지원합니다. SSD 서버는 기본 4,000 IOPS(Input/output Operations Per Second)를 보장하며, 스토리지 크기에 비례하여 성능이 향상하기 때문에 안정적으로 작업을 처리할 수 있습니다.

 

GPU 서버

GPU(Graphics Processing Unit)는 동시에 고성능 연산 처리를 할 수 있도록 최적화된 컴퓨팅 자원입니다. 이미지 프로세싱, 렌더링, 과학 연산, 머신 러닝 등 다양한 영역에 GPU 서버를 활용할 수 있습니다.

 

베어메탈 서버

물리 서버를 가상화 환경 없이 단독으로 제공하는 베어메탈 서버 서비스를 제공합니다. 다른 클라우드 사용자의 영향을 받지 않는 단독 서버를 사용하는 것이기 때문에 성능에 민감한 서비스도 늘 안정적으로 운영할 수 있습니다. 대규모 입출력이 발생하거나 빠른 응답 속도가 필요한 경우에 사용하면 효과적이며, 클라우드 서비스의 편리함과 호스팅 서비스의 안정성을 모두 누릴 수 있습니다. 

 

VDS (Virtual Dedicated Server)

단독으로 제공된 서버 위에서 하나의 클라우드 서버만을 생성해 제공하는 서버

물리 서버 제공 방식이지만 클라우드 서비스 형태로 제공

 

High Availability (HA)

하드웨어에서 발생한 장애가 Virtual Machine(VM) 서버로 확대되는 것을 방지하기 위한 정책으로 호스트 서버에 발생하면 자동으로 호스트 서버 안에 있는 VM 서버를 안정된 다른 호스트 서버로 옮기는 Live Migration을 지원합니다. 하지만 Live Migration을 진행할 수 없는 오류가 발생하면 VM 서버가 재시작됩니다. 

 

Server Image

내 서버 이미지 기능을 이용하면 현재 사용 중인 서버의 이미지를 생성해 서버의 현재 상태를 저장하고 저장한 내 서버 이미지를 이용해 동일한 정보를 가진 서버를 쉽게 생성할 수 있습니다.

 

블록 스토리지

서버 한 대당 최대 2 TB 크기의 스토리지를 15개까지 추가할 수 있습니다. 서버 생성 시 기본 스토리지가 1개 존재하므로 실제로 추가할 수 있는 추가 스토리지는 15개입니다. 

 

스토리지 스냅샷

스냅샷을 생성하여 스토리지 데이터를 저장할 수 있습니다. 생성된 스냅샷을 사용하여 원하는 서버에 새로운 스토리지를 생성하면 저장된 데이터가 복구됩니다.

스냅샷의 원본 스토리지가 연결된 서버와 같은 운영 체제인 서버에만 생성할 수 있습니다

 

방화벽 설정(ACG)

IP 주소/포트 기반 필터링 기능으로 서버로의 네트워크 접근을 관리하는 Security 서비스

 

항목 기준 제공사양
VPC 개수 리전 3개
Subnet 개수 VPC 200개
IP 개수(IPv4) VPC /16-28(65,536개~16개)
NAT Gateway 개수 1개
Network ACL 개수 VPC 200개
Network ACL 규칙 개수 Network ACL 40개
ACG 개수 VPC 500개
ACG 규칙 개수 ACG 50개
ACG 적용 개수 Network Interface 3개
Route Table 개수 VPC 200개
Route Table 규칙 개수 Route Table 50개
VPC Peering 개수 VPC 20개

 

Ncloud Tool Kit (NTK)

터미널 프로그램을 이용하거나 콘솔의 서버 접속 콘솔을 통해 사용할 수 있습니다. 단, Linux에서만 사용할 수 있습니다.

  • Linux 서버 상태 진단
  • IO 테스트
  • GPU 로그 수집
  • NTK에서 수집한 로그 데이터 업로드
  • 시스템 패치
728x90
반응형

'Server > Naver Cloud' 카테고리의 다른 글

Naver Cloud | Networking | VPC, Load Balancer  (0) 2022.09.26
Naver Cloud | Compute | AutoScaling  (1) 2022.09.22
728x90
반응형

1. 컨트롤러 매핑 ( value 지정, 조건 추가 )

package hello.springmvc.basic.requestmapping;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.*;

@RestController
public class MappingController {

    private Logger log = LoggerFactory.getLogger(getClass());

    /**
     * method 특정 HTTP 메서드 요청만 허용
     * GET, HEAD, POST, PUT, PATCH, DELETE
     */
    @RequestMapping(value = "/mapping-get-v1", method = RequestMethod.GET)
    public String mappingGetV1() {
        log.info("mappingGetV1");
        return "ok";
    }


    /**
     * 편리한 축약 애노테이션 (코드보기) * @GetMapping
     *
     * @PostMapping
     * @PutMapping
     * @DeleteMapping
     * @PatchMapping
     */
    @GetMapping(value = "/mapping-get-v2")
    public String mappingGetV2() {
        log.info("mapping-get-v2");
        return "ok";
    }


    /**
     * PathVariable 사용
     * 변수명이 같으면 생략 가능
     *
     * @PathVariable("userId") String userId -> @PathVariable userId
     */
    @GetMapping("/mapping/{userId}")
    public String mappingPath(@PathVariable("userId") String data) {
        log.info("mapping Path userId={}", data);
        return "ok";
    }


    /**
     * PathVariable 사용 다중
     */
    @GetMapping("/mapping/users/{userId}/orders/{orderId}")
    public String mappingPath(@PathVariable String userId, @PathVariable Long
            orderId) {
        log.info("mappingPath userId={}, orderId={}", userId, orderId);
        return "ok";
    }

    /**
     * 파라미터로 추가 매핑
     * params="mode",
     * params="!mode"
     * params="mode=debug"
     * params="mode!=debug" (! = )
     * params = {"mode=debug","data=good"}
     */
    @GetMapping(value = "/mapping-param", params = "mode=debug")
    public String mappingParam() {
        log.info("mappingParam");
        return "ok";
    }

    /**
     * 특정 헤더로 추가 매핑
     * headers="mode",
     * headers="!mode"
     * headers="mode=debug"
     * headers="mode!=debug" (! = )
     */
    @GetMapping(value = "/mapping-header", headers = "mode=debug")
    public String mappingHeader() {
        log.info("mappingHeader");
        return "ok";
    }

    /**
     * Content-Type 헤더 기반 추가 매핑 Media Type
     * consumes="application/json"
     * consumes="!application/json"
     * consumes="application/*"
     * consumes="*\/*"
     * MediaType.APPLICATION_JSON_VALUE
     */
    @PostMapping(value = "/mapping-consume", consumes = "application/json")
    public String mappingConsumes() {
        log.info("mappingConsumes");
        return "ok";
    }

    /**
     * Accept 헤더 기반 Media Type
     * produces = "text/html"
     * produces = "!text/html"
     * produces = "text/*"
     * produces = "*\/*"
     */
    @PostMapping(value = "/mapping-produce", produces = "text/html")
    public String mappingProduces() {
        log.info("mappingProduces");
        return "ok";
    }

}

 

2. CRUD 매핑 ( value 생략 )

package hello.springmvc.basic.requestmapping;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/mapping/users")
public class MappingClassController {

    /**
     * GET /mapping/users
     */
    @GetMapping
    public String users() {
        return "get users";
    }

    /**
     * POST /mapping/users
     */
    @PostMapping
    public String addUser() {
        return "post user";
    }

    /**
     * GET /mapping/users/{userId}
     */
    @GetMapping("/{userId}")
    public String findUser(@PathVariable String userId) {
        return "get userId=" + userId;
    }

    /**
     * PATCH /mapping/users/{userId}
     */
    @PatchMapping("/{userId}")
    public String updateUser(@PathVariable String userId) {
        return "update userId=" + userId;
    }

    /**
     * DELETE /mapping/users/{userId}
     */
    @DeleteMapping("/{userId}")
    public String deleteUser(@PathVariable String userId) {
        return "delete userId=" + userId;
    }
}

 

3. header 매핑 ( Controller 함수 매개변수 )

package hello.springmvc.basic.request;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

@Slf4j
@RestController
@RequestMapping("/headers")
public class RequestHeaderController {

    @RequestMapping
    public String headers(
            HttpServletRequest request,
            HttpServletResponse response,
            HttpMethod httpMethod,
            Locale locale,
            @RequestHeader MultiValueMap<String, String> headerMap,
            @RequestHeader("host") String host,
            @CookieValue(value = "myCookie", required = false) String cookie

            ) {

        log.info("request={}", request);
        log.info("response={}", response);
        log.info("httpMethod={}", httpMethod);
        log.info("locale={}", locale);
        log.info("headerMap={}", headerMap);
        log.info("header host={}", host);
        log.info("myCookie={}", cookie);
        return "OK";
    }

}

 

4. RequestParam

package hello.springmvc.basic.request;

import hello.springmvc.basic.HelloData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

@Slf4j
@Controller
public class RequestParamController {
    /**
     * 반환 타입이 없으면서 이렇게 응답에 값을 직접 집어넣으면, view 조회X
     */
    @RequestMapping("/request-param-v1")
    public void requestParamV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String username = request.getParameter("username");
        int age = Integer.parseInt(request.getParameter("age"));
        log.info("username={}, age={}", username, age);
        response.getWriter().write("ok");
    }

    @ResponseBody
    @RequestMapping("/request-param-v2")
    public String requestParamV2(
            @RequestParam("username") String username,
            @RequestParam("age") int age
    ) throws IOException {
        log.info("username={}, age={}", username, age);
        return "OK";
    }

    @ResponseBody
    @RequestMapping("/request-param-v3")
    public String requestParamV3(
            @RequestParam String username,
            @RequestParam int age
    ) throws IOException {
        log.info("username={}, age={}", username, age);
        return "OK";
    }

    @ResponseBody
    @RequestMapping("/request-param-v4")
    public String requestParamV4(String username, int age){
        log.info("username={}, age={}", username, age);
        return "OK";
    }

    /**
     * @RequestParam.required
     * /request-param-required -> username이 없으므로 예외 *
     * 주의!
     * /request-param-required?username= -> 빈문자로 통과 *
     * 주의!
     * /request-param-required
     * int age -> null을 int에 입력하는 것은 불가능, 따라서 Integer 변경해야 함(또는 다음에 나오는
    defaultValue 사용) */
    @ResponseBody
    @RequestMapping("/request-param-required")
    public String requestParamRequired(
            @RequestParam(required = true) String username,
            @RequestParam(required = false) Integer age) {
        log.info("username={}, age={}", username, age);
        return "ok";
    }

    /**
     * @RequestParam
     * - defaultValue 사용 *
     * 참고: defaultValue는 빈 문자의 경우에도 적용 * /request-param-default?username=
     */
    @ResponseBody
    @RequestMapping("/request-param-default")
    public String requestParamDefault(
            @RequestParam(required = true, defaultValue = "guest") String username,
            @RequestParam(required = false, defaultValue = "-1") int age) {
        log.info("username={}, age={}", username, age);
        return "ok";
    }

    /**
     * @RequestParam Map, MultiValueMap
     * Map(key=value)
     * MultiValueMap(key=[value1, value2, ...]) ex) (key=userIds, value=[id1, id2])
     */
    @ResponseBody
    @RequestMapping("/request-param-map")
    public String requestParamMap(@RequestParam Map<String, Object> paramMap) {
        log.info("username={}, age={}", paramMap.get("username"), paramMap.get("age"));
        return "ok";
    }

    /**
     * @ModelAttribute 사용
     * 참고: model.addAttribute(helloData) 코드도 함께 자동 적용됨, 뒤에 model을 설명할 때
    자세히 설명
     */
    @ResponseBody
    @RequestMapping("/model-attribute-v1")
    public String modelAttributeV1(@ModelAttribute HelloData helloData) {
        log.info("username={}, age={}", helloData.getUsername(),
                helloData.getAge());
        return "ok";
    }

    /**
     * @ModelAttribute 사용
     * 참고: model.addAttribute(helloData) 코드도 함께 자동 적용됨, 뒤에 model을 설명할 때
    자세히 설명
     */
    @ResponseBody
    @RequestMapping("/model-attribute-v2")
    public String modelAttributeV2( HelloData helloData) {
        log.info("username={}, age={}", helloData.getUsername(),
                helloData.getAge());
        return "ok";
    }

}

 

5. RequestBody - String

package hello.springmvc.basic.request;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.nio.charset.StandardCharsets;

@Slf4j
@Controller
public class RequestBodyStringController {

    @PostMapping("/request-body-string-v1")
    public void requestBodyString(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ServletInputStream inputStream = request.getInputStream();
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

        log.info("messageBody={}",messageBody);

        response.getWriter().write("ok");
    }


    /**
     * InputStream(Reader): HTTP 요청 메시지 바디의 내용을 직접 조회 * OutputStream(Writer): HTTP 응답 메시지의 바디에 직접 결과 출력 */
    @PostMapping("/request-body-string-v2")
    public void requestBodyStringV2(InputStream inputStream, Writer responseWriter) throws IOException {
        String messageBody = StreamUtils.copyToString(inputStream,StandardCharsets.UTF_8);
        log.info("messageBody={}", messageBody);
        responseWriter.write("ok");
    }

    /**
     * HttpEntity: HTTP header, body 정보를 편리하게 조회
     * - 메시지 바디 정보를 직접 조회(@RequestParam X, @ModelAttribute X)
     * - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용 *
     * 응답에서도 HttpEntity 사용 가능
     * * */

    @PostMapping("/request-body-string-v3")
    public HttpEntity<String> requestBodyStringV3(HttpEntity<String> httpEntity) throws IOException {
        String messageBody = httpEntity.getBody();
        log.info("messageBody={}", messageBody);

        return new HttpEntity<>("ok");
    }

    @ResponseBody
    @PostMapping("/request-body-string-v4")
    public String requestBodyStringV4(@RequestBody String messageBody) throws IOException {
        log.info("messageBody={}", messageBody);
        return "ok";
    }
}

 

6. Response Body - Json

package hello.springmvc.basic.request;

import com.fasterxml.jackson.databind.ObjectMapper;
import hello.springmvc.basic.HelloData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

@Slf4j
@Controller
public class RequestBodyJsonController {
    private ObjectMapper objectMapper = new ObjectMapper();

    @ResponseBody
    @PostMapping("/request-body-json-v1")
    public String requestBodyJsonV1(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ServletInputStream inputStream = request.getInputStream();
        String messageBody = StreamUtils.copyToString(inputStream, StandardCharsets.UTF_8);

        log.info("messageBody = {}", messageBody);
        HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
        log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());

        return "OK";
    }

    /**
     * @RequestBody HttpMessageConverter 사용 -> StringHttpMessageConverter 적용 *
     * @ResponseBody - 모든 메서드에 @ResponseBody 적용
     * - 메시지 바디 정보 직접 반환(view 조회X)
     * - HttpMessageConverter 사용 -> StringHttpMessageConverter 적용
     */
    @ResponseBody
    @PostMapping("/request-body-json-v2")
    public String requestBodyJsonV2(@RequestBody String messageBody) throws IOException {

        log.info("messageBody = {}", messageBody);
        HelloData helloData = objectMapper.readValue(messageBody, HelloData.class);
        log.info("username={}, age={}", helloData.getUsername(), helloData.getAge());

        return "ok";
    }

    /**
     * @RequestBody 생략 불가능(@ModelAttribute 가 적용되어 버림)
     * HttpMessageConverter 사용 -> MappingJackson2HttpMessageConverter (content-
     * type: application/json)
     */
    @ResponseBody
    @PostMapping("/request-body-json-v3")
    public String requestBodyJsonV3(@RequestBody HelloData data) {
        log.info("username={}, age={}", data.getUsername(), data.getAge());
        return "ok";
    }

    @ResponseBody
    @PostMapping("/request-body-json-v4")
    public String requestBodyJsonV4(HttpEntity<HelloData> httpEntity) {
        HelloData data = httpEntity.getBody();
        log.info("username={}, age={}", data.getUsername(), data.getAge());
        return "ok";
    }

    /**
     * @RequestBody 생략 불가능(@ModelAttribute 가 적용되어 버림)
     * HttpMessageConverter 사용 -> MappingJackson2HttpMessageConverter (content- type: application/json)
     * @ResponseBody 적용
     * - 메시지 바디 정보 직접 반환(view 조회X)
     * - HttpMessageConverter 사용 -> MappingJackson2HttpMessageConverter 적용
     * (Accept: application/json)
     */
    @ResponseBody
    @PostMapping("/request-body-json-v5")
    public HelloData requestBodyJsonV5(@RequestBody HelloData data) {
        log.info("username={}, age={}", data.getUsername(), data.getAge());
        return data;
    }
}
728x90
반응형
728x90
반응형
package hello.servlet.basic.response;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(name = "responseHeaderServlet", urlPatterns = "/response-header")
public class ResponseHeaderServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
        response.setStatus(HttpServletResponse.SC_OK);

        //[status-line]
        response.setStatus(HttpServletResponse.SC_OK); //200

        //[response-headers]
        response.setHeader("Content-Type", "text/plain;charset=utf-8");
        response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("my-header", "hello");

        //[Header 편의 메서드]
        content(response);
        cookie(response);
        redirect(response);

        //[message body]
        PrintWriter writer = response.getWriter();
        writer.println("ok");
    }

    private void content(HttpServletResponse response) {
        //Content-Type: text/plain;charset=utf-8
        //Content-Length: 2
        //response.setHeader("Content-Type", "text/plain;charset=utf-8");
        response.setContentType("text/plain");
        response.setCharacterEncoding("utf-8");
        // response.setContentLength(2); //(생략시 자동 생성)
    }

    private void cookie(HttpServletResponse response) {
        //Set-Cookie: myCookie=good; Max-Age=600;
        // response.setHeader("Set-Cookie", "myCookie=good; Max-Age=600");
        Cookie cookie = new Cookie("myCookie", "good");
        cookie.setMaxAge(600); //600초
        response.addCookie(cookie);
    }

    private void redirect(HttpServletResponse response) throws IOException {
        //Status Code 302
        //Location: /basic/hello-form.html
        //response.setStatus(HttpServletResponse.SC_FOUND); //302
        //response.setHeader("Location", "/basic/hello-form.html");
        response.sendRedirect("/basic/hello-form.html");
    }

}
728x90
반응형
728x90
반응형

아래 옵션으로 편리하게 확인할 수 있다.

 logging.level.org.apache.coyote.http11=debug

 

package hello.servlet.basic.request;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;

@WebServlet(name = "requestParamServlet", urlPatterns = "/request-param")
public class RequestParamServlet extends HttpServlet {


    @Override
    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("[전체 파라미터 조회] - start");

        request.getParameterNames().asIterator()
                .forEachRemaining(paramName -> System.out.println(paramName +
                        "=" + request.getParameter(paramName)));

        System.out.println("[전체 파라미터 조회] - end");
        System.out.println();
        System.out.println("[단일 파라미터 조회]");
        String username = request.getParameter("username");
        System.out.println("request.getParameter(username) = " + username);
        String age = request.getParameter("age");
        System.out.println("request.getParameter(age) = " + age);
        System.out.println();
        System.out.println("[이름이 같은 복수 파라미터 조회]");
        System.out.println("request.getParameterValues(username)");
        String[] usernames = request.getParameterValues("username");
        for (String name : usernames) {
            System.out.println("username=" + name);
        }
        response.getWriter().write("ok");
    }
}

 

728x90
반응형
728x90
반응형
package hello.servlet.basic.request;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "requestHeaderServlet", urlPatterns = "/request-header")
public class RequestHeaderServlet extends HttpServlet {

    @Override
    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        printStartLine(request);
        printHeaders(request);
        printHeaderUtils(request);
        printEtc(request);
        response.getWriter().write("ok");
    }

    //start line 정보
    private void printStartLine(HttpServletRequest request) {
        System.out.println("--- REQUEST-LINE - start ---");
        System.out.println("request.getMethod() = " + request.getMethod()); //GET
        System.out.println("request.getProtocol() = " + request.getProtocol()); // HTTP/1.1
        System.out.println("request.getScheme() = " + request.getScheme()); //http // http://localhost:8080/request-header
        System.out.println("request.getRequestURL() = " + request.getRequestURL()); // /request-header
        System.out.println("request.getRequestURI() = " + request.getRequestURI()); //username=hi
        System.out.println("request.getQueryString() = " + request.getQueryString());
        System.out.println("request.isSecure() = " + request.isSecure()); //https 사용 유무
        System.out.println("--- REQUEST-LINE - end ---");
        System.out.println();
    }

    private void printHeaders(HttpServletRequest request) {
        System.out.println("--- Headers - start ---");
    /*
      Enumeration<String> headerNames = request.getHeaderNames();
      while (headerNames.hasMoreElements()) {
          String headerName = headerNames.nextElement();
          System.out.println(headerName + ": " + request.getHeader(headerName));
      }
    */
        request.getHeaderNames().asIterator()
                .forEachRemaining(headerName -> System.out.println(headerName + ":" + request.getHeader(headerName)));
        System.out.println("--- Headers - end ---");
        System.out.println();
    }


    //Header 편리한 조회
    private void printHeaderUtils(HttpServletRequest request) {
        System.out.println("--- Header 편의 조회 start ---");
        System.out.println("[Host 편의 조회]");
        System.out.println("request.getServerName() = " + request.getServerName()); //Host 헤더
        System.out.println("request.getServerPort() = " + request.getServerPort()); //Host 헤더 System.out.println();
        System.out.println("[Accept-Language 편의 조회]");
        request.getLocales().asIterator().forEachRemaining(locale -> System.out.println("locale = " + locale));
        System.out.println("request.getLocale() = " + request.getLocale());
        System.out.println();
        System.out.println("[cookie 편의 조회]");
        if (request.getCookies() != null) {
            for (Cookie cookie : request.getCookies()) {
                System.out.println(cookie.getName() + ": " + cookie.getValue());
            }
        }
        System.out.println();
        System.out.println("[Content 편의 조회]");
        System.out.println("request.getContentType() = " + request.getContentType());
        System.out.println("request.getContentLength() = " + request.getContentLength());
        System.out.println("request.getCharacterEncoding() = " + request.getCharacterEncoding());
        System.out.println("--- Header 편의 조회 end ---");
        System.out.println();
    }

    // 기타 정보
    private void printEtc(HttpServletRequest request) { System.out.println("--- 기타 조회 start ---");
        System.out.println("[Remote 정보]");
        System.out.println("request.getRemoteHost() = " + request.getRemoteHost()); //
        System.out.println("request.getRemoteAddr() = " + request.getRemoteAddr()); //
        System.out.println("request.getRemotePort() = " + request.getRemotePort()); //
        System.out.println();
        System.out.println("[Local 정보]");
        System.out.println("request.getLocalName() = " + request.getLocalName()); //
        System.out.println("request.getLocalAddr() = " + request.getLocalAddr()); //
        System.out.println("request.getLocalPort() = " + request.getLocalPort()); //
        System.out.println("--- 기타 조회 end ---");
        System.out.println();
    }

}
728x90
반응형
728x90
반응형

application.proper에 추가한다.

/resources/application.properties

logging.level.org.apache.coyote.http11=debug

 

728x90
반응형
728x90
반응형
  • Control + o : 컨트롤러에 서비스 생성
  • Control + r : 마지막 실행했던거 다시 실행

 

  • Command + n : 생성자 생성 
  • Command + alt + v : 객체 인스턴스 생성 
  • Command + alt + l : 코드 자동정렬

 

  • Alt(option) + enter : import class

 

 

  • sout : System out println
  • soutv : 내가 보고싶은 변수 출력
728x90
반응형
728x90
반응형

설정을 추가해준다.

main/resources/apllication.properties

...

server.port=8083

...
728x90
반응형
728x90
반응형

1. Lombok

  필드에 @Autowired 주입 처럼 편하게 사용하는 방법을 제공하는 lombok 라이브러리가 있다.

 

2. build.gradle 파일을 수정한다.

/build.gradle

plugins {
	id 'org.springframework.boot' version '2.7.3'
	id 'io.spring.dependency-management' version '1.0.13.RELEASE'
	id 'java'
}

group = 'hello'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'

	//lombok 라이브러리 추가 시작
	compileOnly 'org.projectlombok:lombok' 
	annotationProcessor 'org.projectlombok:lombok'
	testCompileOnly 'org.projectlombok:lombok'
	testAnnotationProcessor 'org.projectlombok:lombok'
	//lombok 라이브러리 추가 끝


	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
	useJUnitPlatform()
}

 

3. Plugins 를 확인한다.

Preferences -> plugins 검색 -> lombok 검색 -> installed 에 있는지 확인 ( 없으면 설치 )

 

4. Annotation processors 를 설정한다.

 

5. @Getter @Setter Annotation을 확인해본다.

package hello.core;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class HelloLombok {

    private String name;
    private int age;

    public static void main(String[] args) {
        HelloLombok helloLombok = new HelloLombok();
        helloLombok.setName("teepo");

        System.out.println(helloLombok.getName());
    }
}

 

이렇게 따로 Getter, Setter 를 선언해주지 않아도 사용할 수 있다.

 

String에서도 유용한 상황이 있는데,

 

예를 들어 아래의 코드가 있을 때

@Component
public class OrderServiceImpl implements OrderService {

    private MemberRepository memberRepository;
    private DiscountPolicy discountPolicy;

    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }

    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);
        return new Order(memberId, itemName, itemPrice, discountPrice);
    }

    // test
    public MemberRepository getMemberRepository() {
        return memberRepository;
    }
}

 

변수 선언에 final 을 붙이고 생성자를 Annotation으로 만들어 줄 수 있다.

@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);
        return new Order(memberId, itemName, itemPrice, discountPrice);
    }

    // test
    public MemberRepository getMemberRepository() {
        return memberRepository;
    }
}

 

생성자가 한 개였기 때문에 @Autowired 옵션이 자동으로 붙었다.

728x90
반응형

+ Recent posts