포스트

2022-03-18-TIL

Today I Learned

개발자들의 은어

찌르다 : HTTP 요청을 날리거나 네트워크 상의 요청을 날려서 응답을 받아보는 것을 말함. 바라보다 : ‘찌르다’의 수동형, 또는 Consume할 대상 메시지 큐를 가리킬 때의 표현 등으로 사용. 업데이트 치다 : ‘업데이트를 하다’의 은어적 표현. upsert : 없으면 insert, 있으면 새로운 값으로 update 한다. 밀어넣다 : 데이터베이스나 저장 공간에 데이터를 저장하는 것을 말함. (push) 당겨오다 : git pull에서 주로 사용하고, 다른 대상에 대해서 응답으로 받아올 때 사용하기도 함. (pull)

이 중 upsert는 은어라기보다 update와 insert를 합친 데이터베이스 용어다. MySQL의 INSERT ... ON DUPLICATE KEY UPDATE, PostgreSQL의 INSERT ... ON CONFLICT DO UPDATE처럼 DB마다 문법이 따로 있다.


커밋 날짜 바꾸기

Git 커밋에는 작성자 날짜(author date)와 커미터 날짜(committer date) 두 가지가 있다. git-commit 문서에 따르면 --date 옵션은 작성자 날짜를 덮어쓴다. 커미터 날짜는 GIT_COMMITTER_DATE 환경 변수로 지정한다.

1
2
# 직전 커밋의 두 날짜를 모두 바꾼다
GIT_COMMITTER_DATE="2022-03-18T10:00:00" git commit --amend --no-edit --date="2022-03-18T10:00:00"

더 이전 커밋은 git rebase -i로 해당 커밋을 edit으로 표시하고 멈춘 지점에서 같은 방식으로 amend한 뒤 git rebase --continue를 한다. 날짜를 바꾸면 커밋 해시가 바뀌는 히스토리 재작성이므로, 이미 공유된 브랜치라면 강제 푸시가 필요하고 다른 사람의 작업과 충돌할 수 있다.

  • https://velog.io/@astra/git-rebase-%EC%BB%A4%EB%B0%8B-%EC%88%98%EC%A0%95%EB%B3%91%ED%95%A9%EC%82%AD%EC%A0%9C-%EC%82%AC%EC%9A%A9%EB%B2%95
  • https://habitual-history.tistory.com/entry/git-commit-%EB%82%A0%EC%A7%9C-%EB%B0%8F-%EC%8B%9C%EA%B0%84-%EB%B3%80%EA%B2%BD%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95amend?category=1011215

단위 테스트

링크된 글은 단위 테스트의 목표를 다룬다. 단위 테스트는 버그를 찾는 것만이 아니라 소프트웨어 프로젝트가 지속적으로 성장할 수 있게 하는 데 목적이 있다는 관점이다. 테스트가 없으면 코드가 늘수록 변경할 때 무엇이 깨질지 몰라 개발 속도가 떨어지는데, 좋은 테스트는 회귀를 막아 이 속도를 유지하게 해 준다. 반대로 구현 세부 사항에 묶인 테스트는 리팩토링할 때마다 깨져 오히려 유지 비용이 되므로, 테스트 자체의 가치와 비용도 따져야 한다.

  • https://velog.io/@dnr6054/the-goal-of-unit-testing

Android IVI

IVI(In-Vehicle Infotainment)는 차량의 내비게이션, 미디어, 통화, 차량 정보 표시 등을 담당하는 시스템이다. 안드로이드 기반 IVI는 두 갈래로 나뉜다. Android Auto는 스마트폰에서 실행되는 앱 화면을 차량 디스플레이에 투사하는 방식이고, Android Automotive OS는 차량 헤드 유닛에서 안드로이드가 직접 실행되는 운영체제다. 후자는 차량 하드웨어와 HAL로 연결되어 공조 장치나 차량 상태에도 접근할 수 있다.

  • https://www.fpt-software.com/innovation-hub/android-in-vehicle-infotainment-ivi/

AWS CloudFront Content Download

CloudFront로 배포하는 파일을 아무나 내려받지 못하게 하려는 문제다. 오리진인 S3 버킷은 CloudFront를 통해서만 접근하도록 막고, CloudFront 앞단에서 사용자를 인증하는 구조를 쓴다. 링크된 AWS 블로그 글은 Lambda@Edge에서 쿠키에 담긴 토큰을 검사해 인증되지 않은 사용자의 다운로드를 막는 방법을 소개한다. CloudFront 자체 기능으로는 아래의 서명된 URL과 서명된 쿠키가 있다.

  • https://a1010100z.tistory.com/142
  • https://aws.amazon.com/ko/blogs/networking-and-content-delivery/authorizationedge-using-cookies-protect-your-amazon-cloudfront-content-from-being-downloaded-by-unauthenticated-users/

Singed URLs and Signed Cookies

서명된 URL과 서명된 쿠키는 둘 다 만료 시간과 허용 조건을 담은 정책에 개인 키로 서명해서, CloudFront가 서명이 유효한 요청만 통과시키게 하는 기능이다. AWS 문서는 선택 기준을 이렇게 제시한다.

서명된 URL서명된 쿠키
설치 파일처럼 개별 파일 하나에 대한 접근을 제한할 때HLS 동영상의 모든 조각 파일이나 구독자 영역 전체처럼 여러 파일에 접근을 허용할 때
쿠키를 지원하지 않는 클라이언트를 쓸 때기존 URL을 바꾸고 싶지 않을 때

서버는 사용자를 인증한 뒤 서명된 URL을 발급하거나 Set-Cookie로 서명된 쿠키를 내려 준다. 링크된 Java 예제 문서는 서명에 쓸 키 쌍과 URL 생성 코드를 다룬다.

  • https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-choosing-signed-urls-cookies.html
  • https://jayendrapatil.com/tag/signed-urls-vs-signed-cookies/
  • https://liveroomlk.medium.com/cloudfront-signed-urls-cookies-and-s3-presigned-urls-be850c34f9ce
  • https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-cookies.html
  • https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/CFPrivateDistJavaDevelopment.html

AWS 요금 계산

요금 계산기에서 사용할 아키텍처 구성의 스펙을 상세히 입력하고 계산하면 비용이 산정된다.

S3는 저장 용량뿐 아니라 요청 수(PUT, GET 등)와 인터넷으로 나가는 데이터 전송량에도 요금이 붙는다. 그래서 파일 다운로드가 많은 서비스라면 저장 비용보다 전송 비용이 더 클 수 있고, CloudFront를 앞에 두었을 때의 전송 요금과 비교해 보아야 한다. 계산기 결과는 입력한 사용량 가정에 따른 추정치다.

  • https://aws.amazon.com/ko/s3/pricing/
  • https://calculator.aws/#/

Testing

Spring Boot 컨트롤러를 JUnit 5로 테스트하는 방법을 다룬 글들이다. 범위에 따라 @WebMvcTest와 MockMvc로 웹 계층만 검증하는 방법, @SpringBootTest로 전체 컨텍스트를 띄워 검증하는 방법으로 나뉜다. 링크된 reflectoring 글은 컨트롤러 테스트에서 확인할 책임을 HTTP 요청 매핑, 입력 역직렬화, 입력 검증, 비즈니스 로직 호출, 출력 직렬화, 예외 처리로 나누어 설명한다.

  • https://spring.io/guides/gs/testing-web/
  • https://brunch.co.kr/@springboot/418
  • https://velog.io/@devsh/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B6%80%ED%8A%B8-3-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC-%EB%A0%88%EC%9D%B4%EC%96%B4-%ED%85%8C%EC%8A%A4%ED%8A%B8
  • https://www.infoworld.com/article/3543268/junit-5-tutorial-part-2-unit-testing-spring-mvc-with-junit-5.html
  • https://developer.okta.com/blog/2019/03/28/test-java-spring-boot-junit5
  • https://reflectoring.io/spring-boot-web-controller-test/
  • https://howtodoinjava.com/spring-boot2/testing/spring-boot-2-junit-5/
  • https://stackoverflow.com/questions/49096577/how-to-test-spring-5-controllers-with-junit5

Best Practices for Unit Testing

링크된 글들이 공통으로 권하는 원칙은 다음과 같다.

  • 테스트 하나는 한 가지 동작만 검증하고, 이름에 무엇을 검증하는지 드러낸다.
  • given-when-then(또는 arrange-act-assert) 구조로 준비, 실행, 검증을 나눈다.
  • 테스트끼리 상태를 공유하지 않아 실행 순서와 무관하게 통과해야 한다.
  • 구현 세부 사항이 아니라 관찰 가능한 결과를 검증한다.
  • 스프링 컨텍스트가 필요 없는 로직은 컨텍스트 없이 테스트해서 빠르게 유지한다.

  • https://www.baeldung.com/java-unit-testing-best-practices
  • https://tanzu.vmware.com/developer/guides/spring-boot-testing/
  • https://www.diffblue.com/blog/testing/tutorials/the-best-unit-testing-tutorials-for-spring-and-spring-boot/
  • https://phauer.com/2019/modern-best-practices-testing-java/
  • https://howtodoinjava.com/best-practices/unit-testing-best-practices-junit-reference-guide/
  • https://medium.com/personal-capital-tech-blog/testing-best-practices-for-java-spring-apps-762e9fde39ec
  • https://www.javaguides.net/2018/08/junit-framework-best-practices.html?m=1
  • https://thankgodukachukwu.medium.com/unit-and-integrated-testing-spring-boot-and-junit-5-99b9745b782a

Mocking for Testing

의존 객체를 mock으로 바꾸는 방법은 두 가지다. Mockito의 @Mock과 @InjectMocks는 스프링 없이 순수 단위 테스트에서 쓰고, @MockBean은 스프링 컨텍스트에 등록된 빈을 mock으로 교체한다. @MockBean이 다른 테스트 클래스마다 다르게 쓰이면 컨텍스트 캐시를 재사용하지 못해 테스트가 느려진다. 인증이 필요한 컨트롤러는 Spring Security Test의 @WithMockUser로 가짜 사용자를 넣어 테스트한다.

  • https://www.baeldung.com/injecting-mocks-in-spring
  • https://tech.lattechiffon.com/2021/07/03/junit5%EC%99%80-mockito%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-mock-test-java/
  • https://velog.io/@jkijki12/Spring-MockMvc
  • https://smjeon.dev/etc/with-mock-user/
  • https://www.baeldung.com/spring-boot-testing
  • https://meetup.toast.com/posts/124
  • https://www.javainuse.com/spring/springboot_testcases

Integration Testing

통합 테스트는 여러 구성 요소를 실제로 연결한 상태에서 함께 동작하는지 검증한다. Spring Boot에서는 @SpringBootTest로 컨텍스트 전체를 띄우고, webEnvironment = RANDOM_PORT로 실제 서버를 열어 TestRestTemplate이나 WebTestClient로 요청을 보낸다. DB는 내장 H2 대신 운영과 같은 DB를 Testcontainers로 띄우면 SQL 방언 차이로 인한 문제를 미리 잡을 수 있다. 느리므로 핵심 흐름 위주로 작성한다.

  • https://howtodoinjava.com/spring-boot2/testing/spring-integration-testing/
  • https://dzone.com/articles/integration-testing-in-spring-boot-1
  • https://rieckpil.de/guide-to-springboottest-for-spring-boot-integration-tests/
  • https://rieckpil.de/spring-boot-unit-and-integration-testing-overview/
  • https://www.arhohuttunen.com/spring-boot-integration-testing/
참고한 자료외부 출처 2

외부 출처

이 글은 저작권자의 CC BY 4.0 라이선스를 따릅니다.

댓글

아직 댓글이 없습니다