분류 전체보기 50

SpringBoot profile logback

서론 스프링 부트 환경에서 profile별로 로깅 방식과 레벨을 설정해야 했다. 이전에 쓰던 프로젝트의 logback.xml 소스를 받아 그대로 사용해도 됐지만, logback.xml에서 profile마다 로그 레벨과 appender를 지정하는 게 내 눈에는 복잡해 보였고 좀 더 좋은 방법이 없을까 찾아보게 되었다. SpringBoot Logback spring-boot-starter에는 기본적으로 slf4j 인터페이스를 구현한 logback을 사용한다. 사용자는 slf4j를 인터페이스를 사용하는 덕분에, log 구현 라이브러리를 손쉽게 교체할 수 있다. log4j, logback, log4j2가 있고 후자일수록 성능이 더 좋다고 하지만 스프링 부트가 기본적으로 사용하는 logback을 사용하기로 했다...

Backend/Java 2021.06.24

TIL 시작

Today What I Did, 오늘 퇴근 후에 뭐 했나? 취업 전에는 퇴근하고 카페 가서 자기 계발하면서 열심히 해야지~ 했는데 막상 해보니 쉽지 않다😑 야근하고 집 와서 저녁 먹으면서 유튜브 하나 보면 9시 10시 되니까 아무것도 못하겠다. 퇴근하고 카페로 공부하러 바로 간다는 친구 이야기 듣고, '오 대단하네' 생각했는데, 생각보다 더 대단한 놈이었다; 아무튼 자기계발할 시간이 생각보다 많이 부족해서(체력이 안돼서ㅠ), 계획을 바꿨다. 추가적으로 공부하는 건 주말에 하고, 평일에는 배운 거 정리하는 거에 목표를 두자! 이런 식으로 약간 합리화해버렸다. 그래서 이 카테고리에 회사에서 배운 내용을 간단하게나마 기록해보려 한다. 그냥 이렇게 기록이라도 안 하면 다 기억에서 날아갈 거 같은 느낌? 좀 불안..

일상 2021.06.20

Java Stream과 Multi Thread

서론 코딩 테스트를 했을 때, Stream을 사용했는데 사용한 이유에 대해서 면접관이 물어본 적이 있다. 나는 대충 "사람의 언어에 가까운 함수형 프로그래밍으로 가독성이 좋다" 이런 식으로 대답했었다. 면접관은 원하는 대답이 아니었는지, 멀티스레드 환경에서 Stream 장점을 설명해보라 했는데 자세히 알지 못해서 그냥 "하드웨어와 애플리케이션이 멀티스레드 환경이라면 병렬 처리를 지원해줘서 더 좋다"라고 대답했었다. 그러고는 질문이 끊겼는데... 좋은 인상을 준 건 아닌 느낌😰 이번 기회에 Stream과 멀티스레드가 무슨 관계가 있는지 좀 더 자세히 알아보려 한다. Stream 탄생 이유 Collection을 가공하고 처리하는 Java8 API다. 기존의 Collection으로도 요구사항을 다 처리할 수 ..

Backend/Java 2021.04.17

JDBC query vs queryForObject

서론 Spring JDBC를 연습하던 중에 단일 행을 조회하는 데 query를 사용하는 예시를 봤다. query는 List 객체를 반환해 굳이 단일 행을 조회하는 데 query를 쓸 필요가 있나? 하고 queryForObject를 써서 바로 단일 객체로 받아왔다. 정상적으로 작동했고 나름 뿌듯해하면서 예외상황에 대한 테스트 코드를 작성했다. 서비스에서 email를 찾지 못할 시 NotFoundException(404)를 던지게 코드를 작성했다. @Transactional public User login(Email email, String password) { checkNotNull(password, "password must be provided."); User user = findByEmail(emai..

Backend/Java 2021.03.30

Spring Security JWT Token

서론 스프링 시큐리티 볼 때마다 이해하는데 시간 엄청 들이고 넘겼는데, 다시 만나면 제자리다...ㅠ 이번에 프로젝트 샘플코드를 복습하면서 블로그에 정리하려 한다. Session HTTP의 기본적인 상태는 Stateless(무상태), 즉 아무 정보도 저장하지 않는다. request를 같은 사용자가 하더라도, 할 때마다 누가 누군지 모른다는 것이다. 하지만 실제로는 대부분의 웹사이트가 그렇게 작동하지 않는다. 로그인하면 한동안 로그인이 유지되어 있고, 장바구니 같이 회원이 누군지 알아야만 서비스 할 수 있는 기능도 있다. 이를 위해 보통 로그인시 서버 세션에 회원의 정보를 저장해놓고, 요청과 응답에 회원 기본키를 포함시켜 회원을 구분한다. 하지만 이 방법은 서버의 자원을 사용하기 때문에 접속자가 많을 경우 ..

Backend/Java 2021.03.22

@RequestBody 모델에 기본생성자, setter/getter가 필요한가?

서론 최근에 Entity 모델의 속성의 성격을 잘 생각해보고 불변해야 하는 것들은 final로 선언해 명확하게 하라는 코드리뷰를 받았다. 한번 생성되면 변하면 안되는 것들, 이 속성 없이 생성되면 안되는 것들은 추후에 변경돼 에러를 발생시킬 위험이 있고 규모가 커지면 추적하기 어렵다는 것이 이유였다. 오... final! 간단하군! 했는데 여러 문제에 봉착했다. 테스트 코드 작성의 어려움, 객체 변환에 어려움. Builder패턴... 여러가지로 전체적인 코드스타일이 변경되어야 했다. 아무튼, 여러 문제점 중에 여기서 말할 것은 객체 매핑이다. final로 선언된 속성이 있으면 기본생성자는 만들 수 없고 또한 setter 함수도 작성 불가능하다. 그런데 Spring Controller에서 자동으로 객체 매..

Backend/Java 2021.01.21

parse, valueOf 차이와 문제점

평소에 valueOf를 많이 썼는데 valueOf는 예외에 안전하지 않은 함수라서 org.apache.commons.lang3의 toLong을 사용하라는 코드 리뷰를 받았다. 무슨 차이가 있는 걸까? 형변환 함수 자바에서 형변환 할 수 있는 함수는 parse와 valueOf가 있다. parse는 원시형으로 타입을 반환하고 valueOf는 이를 wrap 한 클래스형으로 반환한다. long a = Long.parseLong(1); Long A = Long.valueOf(1); 이러한 형식의 문제점은 변환하려는 값에 문자가 올 경우 예외를 던진다는 것이다. 물론 그럴 가능성은 적겠지만, 안정적인 프로그램을 만들려면 사용자가 넣을 수 있는 값을 모두 고려해야 한다. Long.parseLong("99", 8) /..

Backend/Java 2021.01.21

Repository와 DAO 차이?

서론 Spring MVC를 사용할 때는 DAO를 데이터베이스를 연결하는 객체로 생각하고 여기에 SQL문을 다 넣었었다. JPA를 배우고 난 뒤에 JpaRepository를 구현하면서 DAO는 자연스럽게 Repository로 생각하고 넘겼었다. 그러다 이 둘의 차이를 묻는 질문 글을 발견했고 그 답변의 내용이 상당히 어려웠다. 조금이나마 이해한 것을 번역하면서 글로 정리하지 않으면 다 잊어버릴까 봐 이렇게 글로 나마 정리한다. 내가 이해한 것을 토대로 작성하기 때문에 틀린 내용이 많을 수도 있다. 이 글은 답변 글 번역에 단순히 내 생각을 덧붙인 글로 나는 명확한 차이를 모르겠다. #1 DAO는 data persistence의 추상화다. Repository는 a collection of objects의 추..

Backend/Java 2021.01.14

[Spring Boot] 유효성 검사

※ SpringBoot를 활용한 REST 개발 공부 중, HTTP RequestBody 유효성 검사에 관한 내용을 정리한 자료입니다. @Test @DisplayName("username 없이, POST 회원가입 , 400 badRequest") public void post_whenUsernameIsNull_receiveBadRequest() { User user = TestUtil.createValidUser(); user.setUsername(null); ResponseEntity response = postUser(user, Object.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); } 회원 Entity..

Backend/Java 2020.12.16

Redux test를 위한 export, default export 구분

JS Module Export named export export const App = () => { ... } //import { App } from './App' default export const App = () => { ... }; export default App; // import App from './App' 둘 중 하나만 사용하는 것이 일반적이지만, 두 개 다 사용가능하다. 특히 Redux 테스트를 한다면 두 개 전부 사용하는 것이 유용하다. 둘 중 하나만 사용한다면 번거로운 점이 많아진다. export const App = (props) => { ... }; default export App; Redux 테스트 에러 Provider에 store를 생성해서 props로 줬는데 왜? con..

Frontend 2020.11.08