여태까지 공부하면서 테스트 코드가 가장 어려웠다. 테스트 자체가 어렵다기 보다는 명확하게 잘리지 않은 경계선을 명확하게 잘라내고 구분지어서 '딱 여기서부터 여기까지만. 나머지는 전부 그렇다고 쳐'의 논리 과정을 갖는 것이 쉽지 않았다. 테스트를 이해하는 데에만 시간을 꽤 많이 쏟은 것같은데 오늘 드디어 어느 정도 이해한 느낌을 받아 내용을 정리하고자 한다. 본인이 말하고자 하는 테스트란 유닛 테스트에 한하여 말한다. 유닛 테스트만 할줄 알면 통합 테스트는 식은 죽 먹기라는 말을 본 적이 있는데 그 말에 매우 동의한다. 기본 개념 스프링 내에서 혼자 살아가는 객체는 어느 무엇도 없다. 모든 객체가 크고 작은 요구를 다른 객체에게 해가며 특정 인풋에 대해 특정 액션을 하여 특정 아웃풋을 낸다. 특히 IoC로..
기존에 사용하던 방식은 다음과 같았다. 아무런 문제가 생기지 않아 그냥 한번 잘 만들어두고 잘 복사해서 쓰고 있었는데 이번에 Bootstrap의 modal을 이용하면서 아래와 같은 형태로 사용하면서 에러가 발생했다. th:onclick="|retrievePackageData('${orderItem.trackingNumber}');|" 에러의 내용은 다음과 같다. Caused by: org.attoparser.ParseException: Only variable expressions returning numbers or booleans are allowed in this context, any other datatypes are not trusted in the context of this expressi..
상황은 다음과 같았다. 유저는 상품을 등록할 수 있고 상품은 메인 옵션, 세부 옵션, 가격, 재고라는 한 요소와 공통적인 상품명, 설명, 사진 등을 가진다. 옵션에 관련된 요소는 여러개를 등록할 수 있다. 이 상품을 한번의 요청으로 보낼 수 있어야 한다. 문제는 옵션을 등록하지 않는 경우에 대한 form을 미리 만들어 두었고 같은 페이지를 사용하지만 해당 form을 이용하는 것이 아닌 새로운 방법을 통해 값을 보내고자 하였다. 프론트 먼저 유저가 상품에 대해 등록하면 바로 확인할 수 있게 보여주고자 하였다. 이전에는 createElement라는 방법을 사용했는데 더 찾아보니 cloneNode(true)라는 아주 훌륭한 방법이 있었다. 미리 원본을 만들어두고 그 원본을 복사해서 사용하는 방식이다. 원본은 ..
이 4개는 매일 사용하면서도 매일 헷갈린다. 내용 정리를 확실하게 해놔야 할 필요성을 느껴 정리한다. @RequestBody HTTP 요청으로 넘어오는 body의 내용을 HttpMessageConverter를 통해 Java Object로 역직렬화한다. multipart 요청이 아닌, 즉 어떤 바이너리 파일을 포함하고 있지 않은 데이터를 받는 역할을 한다. HttpMessageConverter란? 간단하게 HTTP 요청과 응답에 대해서 "전략 패턴"을 사용해서 converting 해주는 역할. 전략 패턴은 하나의 메서드가 여러 가지의 대응 방법을 미리 준비해두고 필요한 상황마다 대응 방법을 달리 하는 방법을 말한다. RequestBody는 HTTP 요청으로 같이 넘어오는 Header의 Content-typ..
예를 들어 회원가입을 할 때 유저는 핸드폰 번호를 입력하고 그 핸드폰 번호가 중복이 있는지 요청을 보내고 그에 따라서 검증을 거친 다음 유저에게 정보를 알려줘야 한다. (물론 실무에서는 당연히 외부 API를 이용한 검증을 할 것이므로 핸드폰 번호를 이런 식으로 하진 않을 것이다) 이때 본인이 만든 핸드폰 번호는 Embeddable를 객체로 만들어두어 JPA에서 바로 접근하려고 하면 Embeddable은 객체이고 받아온 값은 데이터라 타입이 맞지 않는 문제가 생겼다. User 객체에 속한 핸드폰 번호 객체. @Embeddable @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @ToString public class PhoneNumber { @Not..
예외 처리는 한 가지 포맷을 통해서 처리하는 것이 가장 좋다. 그리고 그 포맷은 ExceptionHandler와 ControllerAdvice를 이용해서 미리 정해진 ErrorMessage 포맷을 이용한 JSON 데이터로 처리하는 것이 가장 보편적이다. 하지만 혼자서 프로젝트를 진행하여 뷰나 리액트에 깊이가 있지 않으면 렌더링을 위해서 타임리프같은 템플릿 엔진을 사용할 수 밖에 없었기때문에 전체 프로젝트에서 군데군데 타임리프로 예외처리를 하는 일이 발생했다. 단순한 Validation 체크라면 Controller에서 BindingResult를 통해 바로 되돌려 보내면 되지만 Service layer에서 발생하는 비즈니스 로직에 의한 예외 처리가 항상 헷갈렸다. 정확히는 타임리프는 던져지는 예외에 대해서 ..
본인이 옵션을 구현한 방식은 사용자가 직접 옵션을 key-value 형태로 저장 할 수 있고 그 key-value 형태에 따라 서버에 적절히 저장되며 이후에 HTML에서도 dynamic하게 출력될 수 있게 하였다. 프론트에서 서버로 유저가 직접 옵션과 세부 옵션을 추가해서 선택할 수 있게 옵션을 입력하는 input과 그 input을 보여주는 컨테이너를 만들었다. 옵션 추가 사용자가 옵션을 넣고 입력하면 입력값을 적절하게 가공해야한다. 일단 특수문자가 들어올 수 없게 특수문자를 처리해주고 trim해준다. 이후에 "옵션-세부옵션 (삭제버튼)"의 형태로 사용자에게 보여주기 위해 HTML을 적절히 조합해서 사용자가 입력한 옵션의 형태를 볼 수 있게 하였다. 이때 약간 야매스러운 방법을 사용했는데 옵션을 삭제할 ..
공식문서도 NodeJS로 되어있어 다른 자료를 참고했다. 연동 자체는 간단한데 외부 API를 처음 연동해보는거라 여러가지 실수했던 곳이 많아 미래의 실수를 막기 위해 작성한다. https://sumin2.tistory.com/58 스프링부트+jsp로 배달사이트 만들기-40 결제api 사용해서 주문하기(아임포트) https://www.iamport.kr/ 온라인 비즈니스의 모든 결제를 한곳에서, 아임포트 결제의 시작부터 비즈니스의 성장까지 아임포트와 함께하세요 www.iamport.kr 아임포트에 회원가입을 하고 관리자 콘솔로 이 sumin2.tistory.com 위 사이트를 참고했으며 본인은 바닐라 자바스크립트를 이용했다. 자바스크립트 아임포트 Docs에도 나와있듯이 결제 전에 미리 결제 번호를 부여하고..
Page를 꺼내는 방법은 정말 쉽다. 이미 JPA에 의해 다 구현이 되어있으므로 그냥 파라미터로 Pageable을 넘겨서 Page를 리턴받으면 끝이다. 하지만 이 Entity를 DTO로 변환시켜서 넘겨야 하는건 생각보다 까다롭다. Page 인터페이스는 List, Pageable, totalElements 3가지를 가지고 있는 형태라고 볼 수 있다. 하지만 Page로 넘기지않고 PageImpl을 사용한다거나 하면 boundary 값 처리를 직접 해줘야 하는 등 귀찮은 일이 생긴다. 기본적인 구현 방법은 람다식을 이용하여 돌면서 값을 converting 해주면 된다. 여기서 중요한 점은 이때 사용되는 map 함수는 Page 인터페이스의 map이다. 선택하려고 해서 선택할 수 있는 것은 아니지만 map은 St..
하나의 form에서 여러 개의 file을 업로드하고 싶었다. 단순히 input 태그에 multiple을 붙이는게 아닌 파일 업로드가 가능한 필드가 여러개 있는 경우를 말하는 것이다. 정보가 너무 없어서 꽤나 고생했다. HTML에서 업로드부터 시작. form 태그에 enctype="multipart/form-data" 작성 input 태그에 파일 업로드할 곳 작성. name을 신경써서 작성 Controller에서 RequestParam으로 받기 @PostMapping("/write") public String adminWriteAction(@Valid WriteItemRequest writeItemRequest, @RequestParam("mainImage") MultipartFile file, @Requ..
- Total
- Today
- Yesterday
- 레디스
- 배포
- IDE
- RequestParam
- 루나빔
- lunarvim
- JavaScript
- vim
- ModelAttribute
- 아키텍처
- neovim
- RequestPart
- RequestBody
- Dap
- 도커
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |