목록Server application (40)
ecsimsw
배경 발명소 프로젝트 중이었다. 발명소는 신뢰도 있는 프로젝트에서 '변수명', '메서드명', '클래스명' 등 개발자의 작명이 얼마나 보편적으로 사용되는지를 검색할 수 있는 서비스이다. 개발자는 본인의 작명이 얼마나 빈번하게 사용되고, 어떤 상황에서 어떻게 사용되는지 확인할 수 있다. 시운영에서는 백만개를 넘는 코드 파일이 있었고, 테스트에서 가장 많았던 변수명(i) 또는 코드 내 단순 단어 검색은 그 검색 결과가 만개를 훌쩍 넘었다. 우리 팀은 페이지네이션을 적용했고, 그 페이지 수를 프론트 앱에서 결정할 수 있도록 했다. 서버에 보내는 요청 예시는 아래와 같다. i가 변수명으로 사용된 코드 부분을 검색하는데 한 페이지 안에 30개의 검색 결과를 갖는다고 할 때, 두 번째 페이지를 반환해줘. // ex)..
외부 디렉토리 동적 파일 참조 스프링부트에서 파일을 응답하는 법을 정리하려고 한다. 다만 보통 resouces/static에 넣어 사용하는 정적 컨텐츠가 아닌, 실행 도중 동적으로 생성하거나, 관리하는 파일을 다루는 방법을 고민해보았다. 요구 사항 1. 사용자가 실행 도중 업로드한 파일을 저장한다. 2. 저장된 파일의 물리적인 경로를 숨기면서 요청 -> 응답할 수 있도록 하고자 한다. 3. 즉 실제 파일 물리 경로인 card-photos/** 과 달리, 클라이언트의 요청은 /images/cards/** 처럼 명확한 path로 요청할 수 있도록 하고자 한다 방법 위 같은 요구 사항은 다음처럼 ResourceHandler를 사용하면 간단히 해결할 수 있다. 아래처럼 WebMvcConfigurer를 구현하고,..
Blocked by CORS policy 클라이언트 어플리케이션에서 서버로 요청을 보낼 때 만난 문제이다. CORS 정책에 의해서 요청이 제한되었다는데 CORS가 무엇인지, 어떻게 해결했는지 설명하려고 한다. Access to XMLHttpRequest at 'http://localhost:8080/members/login' from origin 'http://localhost:3000' has been blocked by CORS policy : Response to preflight request doesn't pass access control check : No 'Access-Control-Allow-Origin' header is present on the requested resource. 에..
FrontController 패턴이란 기존 서블릿 개발에선 처리 내용 당 서블릿을 정의해줘야하고, 핸들러의 공통 로직들이 매번 중복된다는 문제가 있다. 예를 들면 카페에서 메뉴마다 담당하는 직원이 있다고 생각하자. 아메리카노를 요청하면 아메리카노만을 담당하는 직원이 나와 주문을 받고, 음료를 만들고 포장하고, 카페모카를 요청하면 카페모카만을 담당하는 직원이 나와 주문을 받고, 음료를 만들고 포장해 전달해주고... 매번 반복되는 처리 패턴에서 음료 레시피만 변하고 있다. 반복되는 작업을 전면에서 처리하고, 음료를 만드는 것은 각자 따로 관리되면 어떨까? 매니저는 앞에서 주문받고 계산만하고, 요청 음료를 만들 수 있는 직원에게 음료 제작을 맡기고 음료가 나오면 다시 포장해서 전달하는 즉, 손님의 요청을 '앞..
웹 서버와 WAS 태초의 웹 서버는 정적인 파일만을 요청, 응답하였다. 요청에 해당하는 응답이 항상 일정한 페이지만을 만들 수 있었다. 인터넷이 등장하면서 동적인 페이지에 대한 요구가 증가하였다. 기존의 정적 처리만 가능하던 서버에 동적 처리를 위한 프로그램(Application)을 붙인 Web Application Server를 만들게 되었다. 이를 앞 글자를 따 WAS라고 부른다. 즉, 정적 처리만 가능했던 웹 서버에, Container를 붙여 동적 처리가 가능하도록 한 것이 WAS인 것이다. 이때 Container는 동적 처리를 위한 프로그램들의 구동 환경 제공 정도로 생각하면 된다. 예를 들어 동적 처리를 위한 프로그램을 Servlet이라 한다면, WAS의 Container는 Servlet Con..
양방향 의존성을 피하라 양방향 의존성은 정말 안좋은 참조 패턴이다. '의존'이라는 말마따라 A가 변경될 때 B가 변경되어야하고 B가 변경되면서 다시 A가 영향을 받게된다. '우아한테크세미나'에서 조영호님은 이를 '하나의 클래스로 봐야할 것을 억지로 찢은 형태'라고 표현하셨다. 양방향 의존성은 성능 이슈를 만들고, 양쪽 객체의 싱크를 맞추기 위한 노력이 필요하게 된다. 또 메소드 순환 호출을 야기한다. 이런 양방향 의존을 피하기 위한 패턴으로 다음 두 가지 방식이 자주 소개된다. 1. 인터페이스 사용으로 의존성 분리 2. 중간 객체를 만들어 사이클을 끊는다. 이 두 가지 방식에 대한 예시는 다음에 정리하려고 하고, 이번 글에서는 스프링에서 생성자 주입을 이용하면 이런 양방향 의존을 피할 수 있음을 소개하고..
HandlerMapping과 HandlerAdapter (@포모) 같이 공부하는 친구가 HandlerMapping과 HandlerAdapter의 차이를 질문해주었다. 내가 모호하게 알고 있었다는 것을 펜을 들고 설명하는 순간 알게 되었다. 혼자 머릿속에서 정리하는 것과 말로 설명할 수 있는 것은 정말 차이가 큰 것 같다. 질문을 받는 것은 정말 감사한 일이다. 아 그리고 부끄럽지만 영어 철자를 좀 제대로 봐야겠다. 안다고 생각했던 단어였는데 칠판에 쓰고 설명하려니 철자가 버벅인 경우도 많았다. 웃어 넘겼지만 평소에 조금 더 신경써서 봐야겠다. HandlerMapping FrontController 패턴으로 모든 요청을 DispatcherServlet이 처리한다. DispatcherServlet은 사용자의..
DTO DTO는 Data Transfer Object로 레이어 간 데이터 교환을 위해 사용한다. 예를 들면 Controller에서 View로 출력할 데이터를 넘겨줄 때 DTO를 사용했다. 또는 DB에서 꺼낸 데이터를 담아 가져오기 위해 사용했다. public class GameInfoDto { private final String[][] board; private final double score; public GameInfoDto(String[][] board, double score) { this.board = board; this.score = score; } public GameInfoDto(Board board, Score score) { this(board.parseUnicodeBoard(),..