1. libpng warning: iCCP: known incorrect sRGB profile가 뜨는 원인
파이썬 pygame을 활용해서 프로젝트를 진행 중이었는데 갑자기libpng warning: iCCP: known incorrect sRGB profile 메시지가 떴다. 실행에는 문제가 없었지만 게임이다 보니 frame마다 메시지가 떠서 디버깅하려고 작성한 print문이 보이지 않는 등 불편해서 구글링을 해보니 포토샵으로 이미지 편집을 한 것이 원인이었다. 포토샵에서 이미지 편집을 하면 일반 이미지 파일과 색상 정보를 다르게 저장해서 경고 메시지가 뜨는 것이다.
2. libpng warning: iCCP: known incorrect sRGB profile 해결하기
포토샵으로 편집했던 이미지파일을 연 후 [편집] - [프로필 할당]을 클릭하고, [이 문서 색상 관리 안 함]을 선택 후 확인 버튼을 누르고 저장하면 된다.
<!-- Line Number 적용 -->
<script src="//cdnjs.cloudflare.com/ajax/libs/highlightjs-line-numbers.js/2.7.0/highlightjs-line-numbers.min.js"></script>
<script>hljs.initLineNumbersOnLoad();</script>
블로그 관리 - 꾸미기 - 스킨 편집 - html 편집 - HTML에 위의 코드를 추가합니다.
3. CSS 적용하기
/* Line Number CSS */
/* for block of numbers */
.hljs-ln-numbers {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
text-align: center;
color: #ccc;
border-right: 1px solid #CCC;
vertical-align: top;
padding-right: 5px;
/* your custom style here */
}
/* for block of code */
.hljs-ln-code {
padding-left: 10px;
}
블로그 관리 - 꾸미기 - 스킨 편집 - html 편집 - CSS에 위의 코드를 추가합니다.
4. 결과
이 부분은 블로그 스킨, highlight.js의 스타일에 따라 조금씩 다를 것 같습니다.
저는 Square 스킨, github-gist 스타일을 사용하고 있는데,
라인 넘버 width가 통일되지 않고, 코드 왼쪽에 여백이 적용되지 않는 문제가 있어서 커스텀했습니다.
5. 커스텀 하기
/* Line Number CSS */
/* for block of numbers */
.hljs-ln-numbers {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
text-align: center;
color: #ccc;
border-right: 1px solid #CCC;
vertical-align: top;
width: 25px;
}
/* your custom style here */
.hljs-ln td.hljs-ln-code {
padding-left: 5px;
}
3. CSS 적용하기에서 붙여 넣기 했던 코드를 위의 코드로 바꿔줍니다.
6. 커스텀 결과
커스텀한 결과 라인 넘버 width와 코드 왼쪽 여백이 수정된 것을 볼 수 있습니다.
꼭 저와 동일한 width와 여백을 설정할 필요는 없습니다.
라인 넘버 width를 바꾸고 싶으면 5. 커스텀 하기 코드 15번 라인의 width값을 바꾸면 되고,
코드 왼쪽 여백을 바꾸고 싶으면 5. 커스텀 하기 코드 20번 라인의 padding-left값을 바꾸면 됩니다.
JavaScript에서 함수의 this키워드는 다른 언어와 조금 다르게 동작합니다. 일반 함수의 this는 함수를 호출한 방법이 결정합니다. (동적 스코프 = Dynamic scope) ES5에서 함수를 어떻게 호출했는지 상관하지 않고 this값을 설정할 수 있는 bind 메서드가 도입됐습니다. ES6에서는 this 바인딩을 제공하지 않는 화살표 함수를 추가됐습니다.
화살표 함수에서 this는 항상 상위 스코프의 this를 가리킵니다. (정적 스코프 = Lexical scope = Static scope)
var btn = document.querySelector("#btnXMLHttpRequest");
btn.addEventListener('click', function(){
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", function () {
var data = JSON.parse(oReq.responseText);
var div = document.querySelector("#divAjax");
div.innerHTML = data.result;
});
oReq.open("GET", "<%=request.getContextPath()%>/ajax?type=XMLHttpRequest");
oReq.send();
});
XMLHttpRequest를 이용해서 /ajax에 type=XMLHttpRequest 파라미터를 GET방식으로 보낸 후, 받은 데이터를 divAjax에 표시합니다.
4-2. $.ajax() 코드
$("#btnjQuery").click(function(){
$.ajax({
url : "<%=request.getContextPath()%>/ajax",
data : "type=jQuery",
type : "GET",
success : function(data){
$("#divAjax").html(data.result);
}
});
});
$.ajax()를 이용해서 /ajax에 type=jQuery 파라미터를 GET방식으로 보낸 후, 받은 데이터를 divAjax에 표시합니다.
4-1과 4-2의 코드는 같은 기능을 다른 방법을 이용해서 구현한 것입니다.
5. Controller 코드
@RestController
public class SampleController {
@GetMapping(path="/ajax")
public Map<String, Object> ajax(@RequestParam(name="type") String type){
Map<String, Object> map = new HashMap<>();
String result = type + " Ajax 요청 성공!";
map.put("result", result);
return map;
}
}
파라미터로 받은 type 값 뒤에 " Ajax 요청 성공!"을 더해서 리턴합니다.
6. 전체 코드
sample.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Ajax</title>
<script src="<%=request.getContextPath() %>/js/jquery-3.3.1.js"></script>
</head>
<body>
<h3>XMLHttpRequest/jQuery Ajax</h3>
<button id="btnXMLHttpRequest">XMLHttpRequest Ajax</button>
<button id="btnjQuery">jQuery Ajax</button>
<div id="divAjax" style="width: 250px; height: 50px; margin-top: 5px; border: 1px solid black"></div>
<script>
/* XMLHttpRequest를 이용한 Ajax */
var btn = document.querySelector("#btnXMLHttpRequest");
btn.addEventListener('click', function(){
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", function () {
var data = JSON.parse(oReq.responseText);
var div = document.querySelector("#divAjax");
div.innerHTML = data.result;
});
oReq.open("GET", "<%=request.getContextPath()%>/ajax?type=XMLHttpRequest");
oReq.send();
});
/* jQuery를 이용한 Ajax */
$("#btnjQuery").click(function(){
$.ajax({
url : "<%=request.getContextPath()%>/ajax",
data : "type=jQuery",
type : "GET",
success : function(data){
$("#divAjax").html(data.result);
}
});
});
</script>
</body>
</html>
SampleController.java
package sample.controller;
import java.util.HashMap;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SampleController {
@GetMapping(path="/ajax")
public Map<String, Object> ajax(@RequestParam(name="type") String type){
Map<String, Object> map = new HashMap<>();
String result = type + " Ajax 요청 성공!";
map.put("result", result);
return map;
}
}
실제 서비스 개발을 할 때는 개발용 DB, 테스트용 DB, 서비스용 DB 등이 따로 나눠져있어서 Java 코드는 수정하지 않고, application.properties와 같은 파일만 바꿔서 사용하는 방식으로 각 환경에 필요한 패키지를 빌드한다. 또, Github 등에 코드를 공개할 때 비밀번호처럼 공개되면 안되는 정보들을 properties 파일에 정리한 후 .gitignore를 통해 제외하면 안전하게 관리할 수 있다.
2. application.properties 파일 생성 (src/main/resources/application.properties)