2022-10-17-TIL
2022-10-17-TIL
Today I Learned
RESTful API
REST(Representational State Transfer)는 Roy Fielding이 박사 논문에서 정리한 아키텍처 스타일이다. 클라이언트-서버 분리, 무상태(stateless), 캐시 가능, 균일한 인터페이스, 계층화된 시스템, 선택적인 code on demand라는 제약을 따르는 시스템을 RESTful하다고 부른다. HTTP API에서 균일한 인터페이스는 보통 다음과 같이 드러난다.
- URI는 자원을 가리키는 명사로 짓는다.
/orders/42처럼 쓰고/getOrder?id=42처럼 동작을 넣지 않는다. - 동작은 HTTP 메서드로 표현한다.
GET은 조회,POST는 생성,PUT은 전체 교체,PATCH는 부분 수정,DELETE는 삭제다.GET,PUT,DELETE는 멱등하고POST는 멱등하지 않다. - 결과는 상태 코드로 알린다. 생성 성공은
201 Created와Location헤더, 잘못된 요청은400, 인증 실패401, 권한 없음403, 없는 자원404. - 무상태 제약 때문에 요청마다 필요한 정보(인증 토큰 등)를 모두 담아 보낸다. 서버가 세션을 들고 있지 않으니 서버를 늘리기 쉽다.
Fielding이 말한 REST에는 응답 안의 링크로 다음 상태 전이를 안내하는 HATEOAS까지 포함되지만, 실무의 “REST API”는 대개 위의 자원·메서드·상태 코드 규칙까지만 지키는 경우가 많다.
- https://aws.amazon.com/ko/what-is/restful-api/
- https://www.redhat.com/en/topics/api/what-is-a-rest-api
- https://www.techtarget.com/searchapparchitecture/definition/RESTful-API
- https://restfulapi.net/
- https://gmlwjd9405.github.io/2018/09/21/rest-and-restful.html
- https://meetup.toast.com/posts/92
@RequestParam vs @PathVariable
@PathVariable은 URI 경로의 일부를 값으로 받는다. /users/{id}에서 id처럼 특정 자원을 식별하는 값에 쓴다. @RequestParam은 ?page=2&sort=name 같은 쿼리 파라미터나 폼 데이터를 받는다. 정렬, 필터, 페이지처럼 선택적인 조건에 쓴다. 기본적으로 둘 다 필수값이라 값이 없으면 에러가 나고, @RequestParam(required = false) 또는 defaultValue로 선택값으로 바꿀 수 있다. 경로 변수는 URL 인코딩된 값을 디코딩해서 받고, 쿼리 파라미터는 같은 이름이 여러 번 오면 List로 받을 수 있다.
1
2
3
@GetMapping("/users/{id}/orders")
public List<OrderDto> orders(@PathVariable Long id,
@RequestParam(defaultValue = "0") int page) { ... }
- https://www.baeldung.com/spring-requestparam-vs-pathvariable
- https://ocblog.tistory.com/m/49
Java Call by Value vs Call by Reference
Java는 항상 값에 의한 호출(call by value)이다. 기본형은 값 자체가 복사되고, 참조형은 객체가 아니라 “객체를 가리키는 참조 값”이 복사된다. 그래서 메서드 안에서 전달받은 객체의 필드를 바꾸면 호출한 쪽에서도 보이지만, 매개변수에 새 객체를 대입해도 호출한 쪽의 변수는 그대로다.
1
2
3
4
void change(StringBuilder sb) {
sb.append(" world"); // 같은 객체를 수정: 호출자에게 보인다
sb = new StringBuilder(); // 지역 복사본만 바뀜: 호출자에게 영향 없다
}
이 두 번째 줄이 call by reference였다면 호출자의 변수도 새 객체를 가리켰을 것이다. 이 차이를 보면 Java가 참조를 값으로 넘긴다는 의미가 분명해진다.
- https://velog.io/@ahnick/Java-Call-by-Value-Call-by-Reference
- https://bcp0109.tistory.com/m/360
- https://www.baeldung.com/java-pass-by-value-or-pass-by-reference
- https://kangworld.tistory.com/m/64#:~:text=Call%20by%20value%EB%9E%80%20%ED%95%A8%EC%88%98,%EC%83%9D%EA%B0%81%ED%95%98%EB%A9%B4%20%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0%20%ED%8E%B8%ED%95%98%EB%8B%A4.
Java Memory Structure
JVM 런타임 데이터 영역은 스레드가 공유하는 영역과 스레드마다 따로 갖는 영역으로 나뉜다(JVM Specification: Run-Time Data Areas).
- 공유 영역: 힙(객체와 배열, GC 대상), 메서드 영역(클래스 구조, 런타임 상수 풀, 메서드 코드). HotSpot은 Java 8부터 메서드 영역을 네이티브 메모리의 Metaspace로 구현한다.
- 스레드별 영역: JVM 스택(메서드 호출마다 지역 변수와 연산 중간값을 담은 프레임이 쌓인다), PC 레지스터, 네이티브 메서드 스택.
앞의 call by value 예시와 연결하면, 메서드의 매개변수와 지역 변수는 스택 프레임에 있고 참조형 변수는 힙의 객체를 가리키는 참조 값만 갖는다. 메서드가 끝나면 프레임은 사라지지만 객체는 다른 참조가 남아 있는 동안 힙에 남는다. 힙과 비힙 메모리의 운영 측면은 8월 24일 TIL에 정리했다.
- https://www.javatpoint.com/memory-management-in-java
- https://www.devkuma.com/docs/jvm/memory-structure/
- https://yaboong.github.io/java/2018/05/26/java-memory-management/
- https://www.betsol.com/blog/java-memory-management-for-java-virtual-machine-jvm/
- https://medium.com/platform-engineer/understanding-java-memory-model-1d0863f6d973
- https://steady-coding.tistory.com/m/305
Redis
Redis는 데이터를 메모리에 두는 키-값 저장소다. 값으로 문자열뿐 아니라 리스트, 셋, 정렬된 셋(sorted set), 해시 같은 자료구조를 지원해서, 랭킹(sorted set), 최근 본 목록(list), 중복 제거(set) 같은 기능을 서버 쪽 명령 하나로 처리할 수 있다. 명령은 하나의 스레드에서 차례로 실행되므로 INCR 같은 개별 명령은 원자적이다. 반대로 KEYS *처럼 오래 걸리는 명령은 그동안 다른 모든 요청을 막는다. 메모리 데이터라 재시작에 대비해 RDB 스냅샷이나 AOF 로그로 디스크에 남기는 영속화 옵션이 있고, 키마다 TTL을 줄 수 있어 캐시와 세션 저장소로 많이 쓴다. 장애 대비 구성(Sentinel)은 9월 25일 TIL에 정리했다.
- https://brunch.co.kr/@jehovah/20
- https://any-ting.tistory.com/m/91#:~:text=Redis%EC%97%90%EC%84%9C%20%EC%82%AC%EC%9A%A9%EB%90%98%EB%8A%94%20%EC%9E%90%EB%A3%8C,%EA%B0%99%EC%9D%80%20%EB%8D%B0%EC%9D%B4%ED%84%B0%20%EA%B5%AC%EC%A1%B0%EA%B0%80%20%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4.
- https://pinggoopark.tistory.com/m/280
3-way merge
두 브랜치를 합칠 때 양쪽 끝 커밋만 비교하면, 한쪽에만 있는 줄이 “추가된 것”인지 “다른 쪽에서 지운 것”인지 알 수 없다. 3-way merge는 두 브랜치의 공통 조상(base)을 함께 비교해서 이를 구분한다. base 대비 한쪽만 바뀐 부분은 그 변경을 채택하고, 양쪽이 같은 부분을 다르게 바꿨을 때만 충돌로 남긴다. 한쪽 브랜치가 base에서 전혀 진행하지 않았다면 머지 커밋 없이 포인터만 옮기는 fast-forward가 된다. 머지 기준이 바뀌는 경우의 예시는 8월 9일 TIL에 적었다.
- https://wonyong-jang.github.io/git/2021/02/05/Github-Merge.html
댓글
아직 댓글이 없습니다