HttpServletResopnse에 string 출력하기

response.setContentType("text/html; charset=UTF-8"); response.setCharacterEncoding("UTF-8"); PrintWriter out = response.getWriter(); getOutputStream 의 경우는 바이트 기반 스트림이기 때문에 utf-8로 제대로 인코딩하지 못하는 문제가 있다. https://stackoverflow.com/questions/1992400/how-to-send-through-servletoutputstream-characters-in-utf-8-encoding

2024-09-15 · 1 min · 21 words

HTTP1_1 vs HTTP2_0

탄생 배경 HTTP/1.1 클라이언트가 웹 서버와 정보 교환을 하기위해 만드러진 프로토콜이다. 클라이언트가 서버에게 GET이나 POST 같은 메소드와 함께 요청을 보내면, 서버는 HTML이나 이미지 같은 리소스를 다시 클라이언트에게 보낸다. 이렇게 하나의 요청과 응답을 주고 받는 과정에는 한 개의 애플리케이션 레이어 프로토콜이 사용된다고 생각하면 된다. HTTP/1.1은 아래와 같이 텍스트 기반 형식으로 메시지를 보낸다. GET /index.html HTTP/1.1 Host: www.example.com HTTP/2 Google에서 개발한 SPDY라는 프로토콜을 기반으로 시작되었다. HTTP/2는 압축, 멀티플렉싱, 우선 순위 지정과 같은 기술을 사용해 웹 페이지의 로딩 시간을 줄였다....

2024-09-15 · 5 min · 1021 words

HTTP SameSite 쿠키

목표 SameSite 쿠키가 무엇인지 이해한다. SameSite 쿠키의 정책들을 이해한다. SameSite 쿠키 HTTP 쿠키에 사용할 수 있는 속성으로 cross-site로 요청을 보낼 때 해당 쿠키를 보낼 수 있을지 설정할 수 있다. CSRF 공격에 대한 대응으로 사용할 수 있는 속성이다. SameSite 속성의 쿠키를 설정하려면 아래와 같이 명시하면 된다. Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict SameSite 정책 Strict: 크로스 사이트 요청에 항상 전송하지 않는다. 퍼스트 파티 쿠키만 전송된다. Lax: 이미지나 iframe 에서는 크로스 사이트에 전송하지 않지만, 해당 사이트로 이동할 때 쿠키가 전송된다....

2024-09-15 · 1 min · 101 words

HTTP Client 인터페이스

목표 Spring 6의 HTTP Client 인터페이스가 무엇인지 이해한다. Spring 6의 HTTP Client 인터페이스의 사용법을 이해한다. HTTP Client 인터페이스 Spring Framework 6와 Spring Boot 3부터 사용 가능한 기능 Feign과 같은 클라이언트 라이브러리와 같이 인터페이스를 기반으로 HTTP 요청을 보내고 응답을 받을 수 있는 기능을 제공한다. 사용법 인터페이스 정의 인터페이스 메소드에 어노테이션을 붙이면 된다. 사용 가능한 파라미터 URI: 요청에 대한 URL을 동적으로 설정한다. HttpMethod: 요청에 대한 HTTP 메서드를 동적으로 설정한다. @RequestHeader: 요청 헤더 @RequestBody: 요청 바디 @RequestParam: 요청 매개변수 @CookieValue: 쿠키 이름과 값 사용 가능한 반환 타입 void, Mono<Void> HttpHeaders, Mono<HttpHeaders> <T>, Mono<T> <T>, Flux<T> ResponseEntity<T>, Mono<ResponseEntity<T>> Mono<ResponseEntity<Flux<T>> interface BooksService { @GetExchange("/books") List<Book> getBooks(); @GetExchange("/books/{id}") Book getBook(@PathVariable long id); @PostExchange("/books") Book saveBook(@RequestBody Book book); @DeleteExchange("/books/{id}") ResponseEntity<Void> deleteBook(@PathVariable long id); } 클라이언트 생성 HttpServiceProxyFactory 를 통해서 클라이언트를 생성한다....

2024-09-15 · 1 min · 172 words

HTTP 3와 QUIC

이번에는 현재 IETF의 인터넷 초안 상태인 HTTP/3에 대해서 알아본다. HTTP/3는 기존의 HTTP 버전들과 다르게 TCP를 사용하지 않는다. Transport layer에서 TCP가 아닌 QUIC을 사용한다. QUIC은 Quick UDP Internet Connection의 약자로 구글에서 개발한 UDP기반의 프로토콜이다. 이 QUIC에서 제공하는 기능에는 어떤 것이 있을까. 보안 기존에 TCP + HTTP/2를 사용할 때는 보안을 위해 별도의 TLS 레이어가 필요했다. QUIC은 자체적으로 보안 기능을 내장하고 있어 별도의 TLS 레이어를 둘 필요가 없어졌다. 이렇게 결합하면 어떤 이점이 있을까? 기존의 TCP + TLS의 경우에는 클라이언트와 서버가 연결을 시작할 때 TCP의 3-Way Handshake와 TLS 자체의 Handshake가 따로 필요했었다....

2024-09-15 · 1 min · 194 words

HSTS

목표 HSTS가 무엇인지 이해한다. HSTS를 사용하는 이유를 이해한다. HSTS를 적용하는 방법을 이해한다. HSTS 웹 사이트 접속 시 HTTPS만 사용하도록 클라이언트에서 강제하는 기술이다. 일반적으로, HTTPS를 유도하기 위해서 웹 서버는 리다이렉트 시키는 방법을 사용한다. 이 때, HSTS 헤더(Strict-Transport_security)를 응답으로 주면, 해당 사이트 및 이 사이트의 하위 도메인으로 모든 연결은 HTTPS로 연결이 된다. 사용하는 이유 사용자가 HTTP로 요청을 보내고, HTTPS로 리다이렉트 되는 사이에는 공격자로부터 해당 패킷을 감청할 수 있기 때문이다. HSTS를 사용해서 클라이언트에서 요청을 보낼 때부터 HTTPS를 사용하도록 강제하면 감청 당할 확률이 줄어든다....

2024-09-15 · 1 min · 160 words

Hibernate Validator로 단위 테스트하기

목표 Spring MVC에서 컨트롤러의 파라미터로 사용되는 dto들의 어노테이션 기반 validation을 단위 테스트한다. @SpringBootTest 등을 사용해서 테스트가 느려지게 하지 않는다. 방법 dto를 검증하기위해서는 Validator가 필요하다. Validator는 ValidatorFacotry를 통해서 생성할 수 있다. val validatorFactory = Validation.buildDefaultValidatorFactory() val validator = validatorFactory.validator 아래와 같은 User 클래스가 있다면, validator를 통해서 검증을 통과했는지 테스트 해볼 수 있다. import jakarta.validation.constraints.AssertTrue; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Email; public class User { @NotNull(message = "Name cannot be null") private String name; @AssertTrue private boolean working; @Size(min = 10, max = 200, message = "About Me must be between 10 and 200 characters") private String aboutMe; @Min(value = 18, message = "Age should not be less than 18") @Max(value = 150, message = "Age should not be greater than 150") private int age; @Email(message = "Email should be valid") private String email; // standard setters and getters } // test code Set<ConstraintViolation<User>> violations = validator....

2024-09-15 · 1 min · 162 words

GROUP BY, ORDER BY 사용시 인덱스

인덱스는 정의되어 있는 순서가 중요하다. 만약 인덱스에 정의된 순서가 col1, col2, col3, col4 라고 정의되어 있다면 아래와 같다. GROUP BY col1 # 사용 가능 GROUP BY col1, col2 # 사용 가능 GROUP BY col1, col2, col3 # 사용 가능 GROUP BY col1, col2, col3, col4 # 사용 가능 GROUP BY col2, col2 # 사용 불가능 GROUP BY col1, col3, col2 # 사용 불가능 GROUP BY col1, col2, col3, col4, col5 # 사용 불가능 WHERE 절이 있다고하면 그 다음 컬럼부터 GROUP BY에 있다면 사용 가능하다....

2024-09-15 · 1 min · 113 words

GROUP BY 사용시 filesort가 발생하는 문제 해결하기

MySQL은 GROUP BY 사용시 자동으로 GROUP BY 열에 맞춰 정렬이 발생한다. ORDER BY NULL 를 추가해서 정렬을 하지 않도록 할 수 있다. 참고 자료 https://dba.stackexchange.com/questions/208166/group-by-needs-order-by-null-to-avoid-filesort

2024-09-15 · 1 min · 25 words

Gradle로 멀티 모듈 환경 구성하기

토이 프로젝트를 진행하면서 크롤링 애플리케이션, 조회 애플리케이션을 나누어서 개발하는 상황이 필요했다. 이 때, 두 애플리케이션에서 공통으로 사용되는 엔티티들이 일부 존재했다. 두 애플리케이션에서 공통으로 사용되는 엔티티의 코드를 복사, 붙여넣기로 구현할 수도 있지만 이럴 경우 엔티티의 수정이 있을 때 두 코드에 매번 똑같이 적용해야 되기 때문에 불편함이 있었다. 이를 해결하기 위해 멀티 모듈을 사용해보기로 했다. 구성 hy-notice-core: 두 애플리케이션에서 공통적으로 사용되는 엔티티들을 담고있는 모듈 hy-notice-client: 크롤링에 필요한 로직을 구현 해놓은 모듈 hy-notice-api: 크롤링한 데이터를 조회하기 위해 필요한 api들을 구현 해놓은 모듈 방법 1....

2024-09-15 · 2 min · 347 words

given vs when

목표 mockito의 given과 when 함수의 차이점을 이해한다. Mockito vs. BDDMockito 기본적으로 given과 when함수의 동작은 같다. 둘 다 특정 객체를 목킹하여 함수의 동작을 정의할 때 사용할 수 있다. given은 when을 BDD 스타일로 작성할 수 있도록 만든 함수다. given은 BDDMockito에 정의되어있고, when은 Mockito에 정의되어 있다. BDDMockito는 Mockito 를 상속한 클래스다. BDD(Behavior Driven Development) TDD의 한 종류로 시나리오를 기반으로 테스트 케이스를 작성하여, 개발자가 아닌 사람이 봐도 이해할 수 있을 정도의 테스트 코드를 작성하는 것이다....

2024-09-15 · 1 min · 117 words

Github의 GPG key가 무엇인가

목표 GPG가 무엇인지 알아본다. Github의 verified commit이 무엇인지 알아본다. Github에서 GPG key가 무엇인지 알아본다. GPG란 GPG는 GNU Privacy Guard의 약자로, 파일을 암호화하여 전송할 수 있는 툴이다. GPG는 여러가지 암호화 기술을 제공하지만 기본적으로 RSA 암호화를 사용한다. Github에서 verified commit이 무엇인가? 레포지토리에 커밋을 push할 때, 마치 다른 사람이 커밋한 것처럼 위조할 수 있는 문제점이 있다. git config --global user.name junroot git config --global user.email junroot0909@gmail.com 위의 명령어로 현재 커밋하는 사람의 이름과 이메일만 바꾼다면 쉽게 위조가 가능하다....

2024-09-15 · 1 min · 141 words

Github Actions 개념 이해하기

목표 GIthub Actions를 사용하기 위한 기본 개념을 이해한다. 개념 Workflow 한 개 이상의 job이 실행되는 자동화된 과정 .github/workflows 디렉토리에 yaml 파일로 정의할 수 있다. workflow가 다른 workflow를 참조할 수도 있다. Event workflow 실행을 트리거하는 레포지토리 내의 활동 pull request, issue, push 등 Job 같은 runner에서 실행되는 step의 집합 job들 간에는 기본적으로 의존성이 없고 병렬로 실행된다. 만약 job이 다른 job에 의존성을 설정하면, 의존하는 job이 완료될 때 까지 실행을 기다린다. Step 실행될 수 있는 셸 스크립트 또는 action 각 step은 순차적으로 의존성을 가지고 실행된다....

2024-09-15 · 1 min · 146 words

Git 시작하기

Git이란 버전관리 도구 리누스 토발즈, 2005년 Git 실습 macOS 기준 macOS는 기본적으로 설치되어 있다. sudo brew install git 설치 후 설정 git config --global user.name "MY NAME" git config --global user.email "MY EMAIL" 기존 프로젝트를 git으로 관리하고 싶을 때 git init 새로운 디렉토리를 생성하여 git 저장소를 만들 때 git init (directory path) 파일 상태 확인하기 git status git 파일 관리를 위한 3가지 영역 git directory: 프로젝트의 메타데이터와 객체 데이터베이스를 저장하는 곳 (....

2024-09-15 · 4 min · 704 words

getDeclaredMethods() 와 getMethods() 차이

getDeclaredMethods()는 해당 클래스로부터 직접 정의한 모든 메소드(protected, private 포함)를 반환된다. 하지만 getMethods()는 public 메소드만 반환하지만 부모 클래스로부터 정의된 메소드도 함께 반환된다. https://stackoverflow.com/questions/43585019/java-reflection-difference-between-getmethods-and-getdeclaredmethods

2024-09-15 · 1 min · 22 words

Gatling을 이용한 성능 측정기

시작 하기 Gatling의 시작 방법은 단순하다. 링크에서 압축 파일을 받아서 풀면된다. 주로 유저 시나리오 코드를 user-files/simulations 경로에 넣어두고 bin/gatling.sh 를 통해 실행시키면 된다. 시나리오 작성 하기 시나리오 코드를 작성하고 싶은데 엄청 간단한 툴이 있었다. Gatling에서 Recorder라는 애플리케이션을 제공해주는데 이를 이용하면 아래 두 가지가 가능하다. 브라우저 작업을 추적해 시나리오 코드 작성 HAL 파일을 통해 시나리오 코드 작성 나 같은경우 1번 방법을 사용하면 HTTPS의 웹사이트는 추적이 불가능 한 경우가 있어서 2번 방법을 사용했다....

2024-09-15 · 3 min · 638 words

File 경로 찾기

String resourceName = "example_resource.txt"; ClassLoader classLoader = getClass().getClassLoader(); File file = new File(classLoader.getResource(resourceName).getFile()); String absolutePath = file.getAbsolutePath(); System.out.println(absolutePath); assertTrue(absolutePath.endsWith("/example_resource.txt")); ClassLoader를 사용하면 classpath에서 해당 파일의 위치를 찾는다. 서브 디렉토리까지 찾지 않는 점의 유의해야된다. 참고 자료 https://www.baeldung.com/junit-src-test-resources-directory-path

2024-09-15 · 1 min · 35 words

FactoryBean

상황 코드에서 FactoryBean이라는 인터페이스를 빈으로 등록하는 부분이 있었는데, 어떤 용도인지 궁금했다. Factory Bean의 역할 다른 Bean을 생성하고 Spring IoC 컨테이너에 등록하는 Bean이다. 사용 예시 JndiObjectFactoryBean: JNDI에서 데이터 소스를 조회하는데 사용 ProxyFactoryBean: AOP를 사용하여 bean에 대한 프록시를 생성하는데 사용 Factory Bean 생성하는 방법 FactoryBean 인터페이스의 구현체를 빈으로 등록한다. AbstractFactoryBean을 확장한다. 이 추상 클래스는 getObjectType()과 createInstance() 메서드만 구현하면된다. 해당 추상 클래스에서는 싱글톤 패턴을 사용하고 있어 쉽게 싱글톤으로 빈을 관리할 수 있게해준다. 참고 자료 https://www....

2024-09-15 · 1 min · 72 words

express에서 request body 가져오는 법

express에서 POST 요청의 request body를 가져오지 못하는 문제가 있었다. 이를 해결하기 위해서는 express가 body 정보를 parsing할 수 있도록 별도의 설정을 해야된다. body-parser이라는 패키지를 가져와서, express app에서 사용하도록 설정해준다. 여기서 body-parser는 이름과 같이 raw body를 가져와서 파싱을 해준다. 나는 json content-type의 body 정보를 가져올 것이기 때문에 아래와 같이 설정했다. 다른 content-type을 사용할 경우에는 아래와 동일한 방법으로 추가해줄 수 있다. const express = require('express'); const bodyParser = require('body-parser'); const app = express(); app....

2024-09-15 · 1 min · 71 words

ExecutorService 이해하기

목표 ExecutorService의 역할을 이해한다. ExecutorService의 대표적인 메서드를 이해한다. Runnable 스레드에 의해 실행될 작업을 나타내는 함수형 인터페이스 void run() 메서드를 가지고 있다. Executor Runnable 작업을 실행시켜주는 인터페이스 실행 작업과 각 작업이 실행되는 메커니즘(스레드 사용, 스케쥴링 등)을 decoupling 시켜주는 인터페이스이다. 일반적으로 executor에서 실행되는 작업은 다른 스레드에서 실행된다. class ThreadPerTaskExecutor implements Executor { public void execute(Runnable r) { new Thread(r).start(); } } 하지만 Executor의 구현체가 항상 비동기나 다른 스레드로 실행되어야 한다는 제한은 없다. class DirectExecutor implements Executor { public void execute(Runnable r) { r....

2024-09-15 · 2 min · 355 words