![개발자도구만 열면 CSS가 깨지는 이유? DevTools 재정의 문제 해결](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb23Kj9%2FbtsMft3yqoR%2FM2t3XDkG0uKyTvw7VaZdf1%2Fimg.jpg)
개발 중 CSS가 어떻게 적용되는지 확인하기 위해 크롬 개발자도구(DevTools)를 열었는데 의도한 CSS가 적용되지 않는 문제가 생겼다.처음 페이지를 로드할 때는 제대로 보였지만, 개발자도구를 열기만 하면 이전의 CSS로 적용이 되는 현상이 발생했다.사파리나 다른 브라우저에서는 아무런 문제가 없었다.이 문제를 해결하는 과정에서 Chrome DevTools의 Override 기능을 알게 되었고, 이를 활용하는 방법까지 정리해 보았다.1. 이상한 점 발견 : "style.css"만 문제?내 프로젝트에서는 Tailwind를 사용 중이었고, 빌드 후에는 Tailwind CSS는 일반 CSS로 변환된다.(이 부분은 Tailwind CSS 사용하기(3 버전)에 정리해두었다.)처음엔 Tailwind의 빌드 문제를..
![Tailwind CSS 사용하기(3 버전)](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwh2E9%2FbtsMerYFV8O%2Fi7HZjmq69ukSElCRIfP4C1%2Fimg.jpg)
1. CLI로 사용하는 방법1.1 Tailwind 설치1.1.1 npm을 사용한 설치npm init -y npm install -D tailwindcssnpx tailwindcss init1.1.2 npm 없이 실행하기 (맥북용)curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-macos-x64chmod +x tailwindcss-macos-x64mv tailwindcss-macos-x64 tailwindcss./tailwindcss init1.2 input.css 생성@tailwind base;@tailwind components;@tailwind utilities;이 파일을 통해 실제 CS..
![DispatcherServet 커스텀 구현 시 주의할 점](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbicl9X%2FbtsMesa1Qvb%2F6Ju2fNpd0SKxznJe351t2K%2Fimg.jpg)
스프링의 DispatcherServlet을 서블릿으로 커스텀 구현할 때 과거에는 *.do 방식으로 요청을 가로챘기 때문에 상관없었지만, 루트 경로(/)를 활용해서 모든 요청을 가로채는 방식에는 정적 리소스와 관련해서 주의해야 할 점이 있다.이 글에서는 주의할 점과 문제를 해결하는 방법, 그리고 실제 스프링에서 매핑을 처리하는 방식에 대해 알아보겠다.1. 과거의 '*.do' 방식과거에는 *.do로 요청을 가로채는 방식으로 DispatcherServlet을 만들었기 때문에 JSP나 정적 리소스 요청과 서블릿 요청이 섞이지 않았다.정적리소스는 DefaultServlet이 처리하고, jsp는 JspServlet이 처리하고 동적 요청은 *.do 끝나기 때문에 DispatherServlet이 처리했다.그런데 이 방..
![@NotNull, @NotEmpty, @NotBlank 비교](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXRGU8%2FbtsL9tAMYFR%2F0wePEwEnlKfRJI5RMHYn00%2Fimg.jpg)
@NotNull, @NotEmpty, @NotBlank는 스프링에서 유효성 검사를 할 때 사용하는 어노테이션들이다.각각의 어노테이션들은 역할이 유사해보이지만, 허용하는 값의 범위가 다르다. 차례대로 설명해보겠다.1. @NotNull특징null값을 허용하지 않는다.문자열의 경우, 빈 문자열("") 또는 공백 문자열(" ")은 허용된다.사용 예시public class UserDTO { @NotNull(message = "이름은 null일 수 없습니다.") private String name;}사용 시 참고객체나 필드가 반드시 초기화되어야 할 때 사용한다.단, 문자열이 비어 있거나 공백만 있는지에 대한 검증은 하지 않는다.2. @NotEmpty특징null과 빈 문자열("")을 허용하지 않는다.공백 ..
![스프링 부트 3.4부터 @MockBean이 deprecated되고 @MockitoBean으로 변경된 이유](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsJrli%2FbtsL2I0KuMm%2FePoTJvrxOiHsGwdbu9Mh9K%2Fimg.jpg)
스프링 부트 3.4 버전부터는 @MockBean이 deprecated 되고, @MockitoBean으로 대체되었다.여기서 끝내긴 좀 그러니 관련해서 좀 더 글을 써보겠다..1. @MockBean이란?@MockBean은 스프링 부트가 제공하는 어노테이션이다.가짜 객체(틀만 있는 객체)를 bean으로 만드는 역할을 한다. 예를 들어 service를 만들 때 repository를 사용하는 경우가 많다.테스트를 진행할 때 repository가 무조건 제대로 작동한다고 가정하고 service에 집중해서 테스트하고 싶을 때 repository를 mock으로 빈 주입을 해준다.즉, repository는 실제 동작하는 것이 아니라 호출이 되었는지, 되었다면 몇 번이나 되었는지 등의 행위만 검증할 때 사용한다.사용예시@..
![서블릿 매핑 우선순위](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGcUKO%2FbtsL300ccw9%2F00Zl5sAYyUidEpsIaK6XBK%2Fimg.jpg)
서블릿 매핑 규칙서블릿 매핑은 우선순위가 존재하며 가장 먼저 성공한 매핑이 사용되고 이후 매칭은 시도하지 않는다.다음은 1번부터 차례대로 우선순위를 가지는 매핑이다.정확한 경로 매핑 (Exact Match)요청 경로가 서블릿 매핑과 정확히 일치하면 해당 서블릿이 선택예: /catalog 요청이 /catalog로 매핑된 서블릿에 전달경로 기반 매핑 (Path Mapping)서블릿 컨테이너는 요청 경로와 매핑 패턴이 가장 긴 경로를 선택매핑은 디렉토리 구조처럼 계층적으로 탐색되며, /문자를 경로 구분자로 사용예: /foo/bar/index.html요청이 들어왔을 때 foo/bar/*와 foo/* 매핑이 있다면 foo/bar/*로 매핑된 서블릿에 요청 전달확장자 매핑 (Extension Mapping)요청 경..
![Jsp 사용할 때 루트 경로에서 index.jsp가 작동하는 이유](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FduPH08%2FbtsL1igCf7w%2Fm0xB9YrukkVwRFehoIXnvK%2Fimg.jpg)
Jsp 기반 웹 애플리케이션을 개발할 때, webapp 디렉토리 아래에 index.jsp 파일만 있어도 루트 경로(/)로 접근 시 자동으로 index.jsp가 실행된다.1. index 파일 처리 개략적 과정루트 경로("/")로 요청이 들어오면, 톰캣은 웰컴 파일 목록(welcome-file-list)을 먼저 확인한다.웰컴파일이 발견되면, 해당 파일로 내부 포워드하여 처리한다.파일이 jsp확장자라면 JspServlet이 처리하고, html이라면 DefaultServlet이 처리한다.2. 톰캣의 웰컴 파일 목록톰캣은 기본적으로 conf/web.xml 파일에 아래와 같이 웰컴 파일 목록을 정의해둔다. index.html index.htm index.jsp 루트..
![JSP 동작 원리](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4hEtH%2FbtsLWP50iZD%2Far0uKKFtaAnpPtDOhhxFtK%2Fimg.jpg)
JSP는 서버에서 웹 페이지를 동적으로 생성하기 위한 기술이며 실행시점에 서블릿으로 변환되어 처리된다.JSP가 처리되는 방식에 대해서 더 자세히 살펴보도록 하겠다.1. JSP 동작 방식JSP 파일은 클라이언트의 최초 요청이 들어올 때 서블릿으로 변환되고, 이후에는 변환된 클래스를 재사용하는 방식으로 동작한다.즉, 다음과 같은 단계로 처리된다.클라이언트가 JSP 파일 요청JSP엔진(Jasper)이 JSP 파일을 서블릿 자바 코드로 변환하고 컴파일하여 클래스 파일을 생성한다.변환된 서블릿 클래스가 메모리에 로드되고, 클라이언트 요청을 처리한다.최초 변환 후에는 JSP파일이 변환되지 않는 한 매번 변환 및 컴파일 과정을 거치지 않고 기존 변환된 서블릿 클래스를 재사용한다.그리고 jsp에서 변환된 서블릿은 일반..
![Docker Compose](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHlr1R%2FbtsLQ7GFeK7%2FciqFSwdI5LrKGwKBw9sdCk%2Fimg.jpg)
1. Docker Compose 개념여러 개의 Docker 컨테이너들을 하나의 서비스로 정의해서 하나의 묶음으로 관리할 수 있게 해주는 도구이다.2. Docker Compose 사용 이유여러 개의 컨테이너 한번에 관리예를 들어 Spring project를 사용하면 Database도 같이 사용하게 되는 경우가 많다.그럴 때 Docker Compose를 사용하면 각 컨테이너를 독립적으로 관리하는 것이 아니라 하나의 환경에서 실행하고 관리해준다.복잡한 명령어 간소화지금까지 컨테이너를 띄울 때 명령어가 복잡해지는 경우가 많았다. MySQL을 띄울 때 명령어를 다시 확인해보자.docker run -e MYSQL_ROOT_PASSWORD=pwd1234 -p 3306:3306 -v /Users/choijaehun/D..
![Dockerfile](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrGs5n%2FbtsLQuacP9b%2FpELzFzLGLTYkRaDp11ayaK%2Fimg.jpg)
1. Dockerfile이란Docker 이미지는 Dockerhub을 통해 다운받아서 사용할 수 있다.즉, Dockerhub에 있는 이미지들은 누군가 만들어서 업로드 해놓은 것이다.그리고 그 이미지는 Dockerfile로 만들 수 있다.예를 들어서 내가 만든 Spring boot 프로젝트를 Docker 이미지로 만들고 싶다면 Dockerfile을 활용하면 된다.즉, Dockerfile은 Docker 이미지를 만들게 해주는 파일이다.2. Dockerfile에 쓰이는 명령어2.1 FROM: 베이스 이미지 생성2.1.1 의미FROM은 베이스 이미지를 생성하는 역할을 한다. 즉 Dockerfile로 이미지를 만들 때 기반이 되는 이미지를 세팅하는 것이다.예를 들어 Spring boot 프로젝트 배포를 위한 이미지..
![바인드 마운트](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxvwrj%2FbtsLPDcKoFP%2F3Sm4KhP2grDkKcZZsL5Kk0%2Fimg.jpg)
1. 바인드 마운트의 필요성Docker를 활용하면 프로그램을 컨테이너로 띄울 수 있다.컨테이너는 호스트 컴퓨터에서 만드는 작은 컴퓨터이다. 컨테이너를 종료하는 것은 호스트 컴퓨터에서 컨테이너를 제거하는 것이다.이렇게 제거가 되면 컨테이너 내부에 있던 데이터들도 같이 삭제가 된다. 예를 들어, MySQL 컨테이너를 사용하다가 컨테이너를 교체하거나 삭제하게 되면 내부의 데이터도 같이 삭제된다.이 문제는 바인드 마운트를 사용하면 해결할 수 있다.2. 바인드 마운트란?바인드 마운트는 도커 컨테이너와 호스트 컴퓨터 간에 특정 디렉토리를 연결하여 데이터를 실시간으로 공유하는 방법이다.컨테이너의 저장 공간에 데이터를 저장하는 것이 아니라 호스트 컴퓨터의 저장 공간을 공유해서 사용한다.이를 통해 컨테이너를 삭제하더라도..
![자주 사용하는 도커 명령어](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJbh8L%2FbtsLNXioOir%2FSwoGEyxLM2DNbs6Kva6l81%2Fimg.jpg)
1. 이미지 다운로드이미지를 다운로드 할 때 Dockerhub에서 이미지를 다운 받는다.Github에 사람들이 코드를 저장해두고 clone, pull을 통해 사용하듯이 Dockerhub도 사람들이 올려놓은 이미지들이 저장되어 있어서 pull을 통해 다운 받아서 사용할 수 있다.즉 Dockerhub는 Github처럼 이미지를 저장하고 다운받을 수 있는 저장소 역할을 한다.1.1 최신 버전 이미지 다운로드 명령어docker pull 이미지명 # docker pull 이미지명:latest 와 동일1.2 특정 버전 이미지 다운로드 명령어docker pull 이미지명:태그명태그명은 특정 버전을 나타내는 이름이다.예를 들어 dockerhub에서 nginx 이미지를 다운받는다고 했을 때 아래와 같이 다운 받을 수 있..