ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,45 @@
+package controller;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import service.UserJoinService;
+import util.HttpRequest;
+import util.HttpResponse;
+
+public class UserController {
+    private final String HTTP_GET = "GET";
+    private final String JOIN_FORM = "/user/form.html";
+    private final String CREATE_USER_URL = "/user/create";
+    private UserJoinService userJoinService;
+    private Logger log = LoggerFactory.getLogger(getClass());
+
+    public UserController(UserJoinService userJoinService) {
+        this.userJoinService = userJoinService;
+    }
+
+    // TODO : 에러페이지 생성, 회원가입 검증
+    public String process(HttpRequest request, HttpResponse response) {
+        // GET 요청인 경우 분리
+        if (request.getMethod().equals(HTTP_GET)) {
+            // 회원 가입 폼 보여주기
+            if (request.getUrl().equals(JOIN_FORM)) {
+                return JOIN_FORM;
+            }
+            // 회원가입일 경우
+            if (request.getUrl().equals(CREATE_USER_URL)) {
+                return addUser(request.getQueryString(), response);
+            }
+        }
+
+        return "/error";
+    }
+
+    private String addUser(String queryParameters, HttpResponse response) {
+        userJoinService.addUser(queryParameters);
+
+        response.setStatus(302);
+        response.setHeader("Location", "/index.html");
+        return response.getResponse();
+    }
+
+}

리뷰: ```suggestion
            if (request.getUrl().equals(JOIN_FORM)) {
                return JOIN_FORM;
            }
```
두 개 값이 같아서 이 코드와 같은 의미입니다.
@@ -0,0 +1,45 @@
+package controller;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import service.UserJoinService;
+import util.HttpRequest;
+import util.HttpResponse;
+
+public class UserController {
+    private final String HTTP_GET = "GET";
+    private final String JOIN_FORM = "/user/form.html";
+    private final String CREATE_USER_URL = "/user/create";
+    private UserJoinService userJoinService;
+    private Logger log = LoggerFactory.getLogger(getClass());
+
+    public UserController(UserJoinService userJoinService) {
+        this.userJoinService = userJoinService;
+    }
+
+    // TODO : 에러페이지 생성, 회원가입 검증
+    public String process(HttpRequest request, HttpResponse response) {
+        // GET 요청인 경우 분리
+        if (request.getMethod().equals(HTTP_GET)) {
+            // 회원 가입 폼 보여주기
+            if (request.getUrl().equals(JOIN_FORM)) {
+                return JOIN_FORM;
+            }
+            // 회원가입일 경우
+            if (request.getUrl().equals(CREATE_USER_URL)) {
+                return addUser(request.getQueryString(), response);
+            }
+        }
+
+        return "/error";
+    }
+
+    private String addUser(String queryParameters, HttpResponse response) {
+        userJoinService.addUser(queryParameters);
+
+        response.setStatus(302);
+        response.setHeader("Location", "/index.html");
+        return response.getResponse();
+    }
+
+}

리뷰: response 구조를 적극 코드에 반영하셨네요!
@@ -0,0 +1,45 @@
+package controller;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import service.UserJoinService;
+import util.HttpRequest;
+import util.HttpResponse;
+
+public class UserController {
+    private final String HTTP_GET = "GET";
+    private final String JOIN_FORM = "/user/form.html";
+    private final String CREATE_USER_URL = "/user/create";
+    private UserJoinService userJoinService;
+    private Logger log = LoggerFactory.getLogger(getClass());
+
+    public UserController(UserJoinService userJoinService) {
+        this.userJoinService = userJoinService;
+    }
+
+    // TODO : 에러페이지 생성, 회원가입 검증
+    public String process(HttpRequest request, HttpResponse response) {
+        // GET 요청인 경우 분리
+        if (request.getMethod().equals(HTTP_GET)) {
+            // 회원 가입 폼 보여주기
+            if (request.getUrl().equals(JOIN_FORM)) {
+                return JOIN_FORM;
+            }
+            // 회원가입일 경우
+            if (request.getUrl().equals(CREATE_USER_URL)) {
+                return addUser(request.getQueryString(), response);
+            }
+        }
+
+        return "/error";
+    }
+
+    private String addUser(String queryParameters, HttpResponse response) {
+        userJoinService.addUser(queryParameters);
+
+        response.setStatus(302);
+        response.setHeader("Location", "/index.html");
+        return response.getResponse();
+    }
+
+}

리뷰: 이 부분을 없애고 범용적인 메서드로 따로 빼서 리팩토링할 수 있을 것 같아요.
@@ -0,0 +1,56 @@
+package util;
+
+public class HttpRequest {
+
+    private String method;
+    private String url;
+    private String queryString;
+
+    public HttpRequest(String line) {
+        String[] splitHeader = line.split(" ");
+        // uriPath = 전체 uri (쿼리 파라미터 분리 전)
+        String uriPath = getURIPath(splitHeader);
+
+        // 쿼리 파라미터 분리 후 url
+        this.url = getPath(uriPath);
+        this.method = splitHeader[0];
+        this.queryString = getQueryParameters(uriPath);
+    }
+
+    public String getMethod() {
+        return method;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public String getQueryString() {
+        return queryString;
+    }
+
+    @Override
+    public String toString() {
+        return "HttpRequest{" +
+                "method='" + method + '\'' +
+                ", url='" + url + '\'' +
+                ", queryString='" + queryString + '\'' +
+                '}';
+    }
+
+    private String getURIPath(String[] splitHeader) {
+        return splitHeader[1];
+    }
+
+    private String getPath(String uriPath) {
+        return uriPath.split("\\?")[0];
+    }
+
+    private String getQueryParameters(String uriPath) {
+        String[] split = uriPath.split("\\?");
+        if (split.length > 1) {
+            return split[1];
+        }
+        return "";
+    }
+}

리뷰: 쿼리를 String으로 저장하도록 구현하신 이유가 있나요?
@@ -0,0 +1,81 @@
+package util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.Map;
+
+public class HttpResponse {
+
+    private Logger log = LoggerFactory.getLogger(getClass());
+    private int status;
+    private Map<String, String> headers = new HashMap<>();
+
+    public void processResponse(String path, HttpResponse response, OutputStream out) throws IOException {
+        String contentType = response.getContentType(path);
+        byte[] body = findBody(contentType, path);
+        DataOutputStream dos = new DataOutputStream(out);
+        responseHeader(dos, body.length, contentType);
+        responseBody(dos, body);
+    }
+
+
+    private void responseHeader(DataOutputStream dos, int lengthOfBodyContent, String contentType) {
+        try {
+            dos.writeBytes("HTTP/1.1 " + status + " " + getStatusCode(status) + "\r\n");
+            dos.writeBytes("Content-Type: " + contentType + "\r\n");
+            dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n");
+
+            for (Map.Entry<String, String> header : headers.entrySet()) {
+                dos.writeBytes(header.getKey() + ": " + header.getValue() + "\r\n");
+            }
+
+            dos.writeBytes("\r\n");
+        } catch (IOException e) {
+            log.error(e.getMessage());
+        }
+    }
+
+    private void responseBody(DataOutputStream dos, byte[] body) {
+        try {
+            dos.write(body, 0, body.length);
+            dos.flush();
+        } catch (IOException e) {
+            log.error(e.getMessage());
+        }
+    }
+
+    private String getContentType(String path) {
+        return ContentType.findContentType(path).getValue();
+    }
+
+    private byte[] findBody(String contentType, String path) throws IOException {
+        return Files.readAllBytes(new File(ResponseBody.findResponseBody(contentType).getPath() + path).toPath());
+    }
+
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+    public void setHeader(String name, String value) {
+        headers.put(name, value);
+    }
+
+    private String getStatusCode(int status) {
+        if (status == HttpStatus.MOVED_TEMPORARILY.getValue()) {
+            return HttpStatus.MOVED_TEMPORARILY.getReason();
+        }
+
+        return HttpStatus.OK.getReason();
+    }
+
+    public String getResponse() {
+        return headers.getOrDefault("Location", "");
+    }
+}

리뷰: path가 `/fonts/~` 이렇게 요청들어오지 않나요?
@@ -0,0 +1,81 @@
+package util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.Map;
+
+public class HttpResponse {
+
+    private Logger log = LoggerFactory.getLogger(getClass());
+    private int status;
+    private Map<String, String> headers = new HashMap<>();
+
+    public void processResponse(String path, HttpResponse response, OutputStream out) throws IOException {
+        String contentType = response.getContentType(path);
+        byte[] body = findBody(contentType, path);
+        DataOutputStream dos = new DataOutputStream(out);
+        responseHeader(dos, body.length, contentType);
+        responseBody(dos, body);
+    }
+
+
+    private void responseHeader(DataOutputStream dos, int lengthOfBodyContent, String contentType) {
+        try {
+            dos.writeBytes("HTTP/1.1 " + status + " " + getStatusCode(status) + "\r\n");
+            dos.writeBytes("Content-Type: " + contentType + "\r\n");
+            dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n");
+
+            for (Map.Entry<String, String> header : headers.entrySet()) {
+                dos.writeBytes(header.getKey() + ": " + header.getValue() + "\r\n");
+            }
+
+            dos.writeBytes("\r\n");
+        } catch (IOException e) {
+            log.error(e.getMessage());
+        }
+    }
+
+    private void responseBody(DataOutputStream dos, byte[] body) {
+        try {
+            dos.write(body, 0, body.length);
+            dos.flush();
+        } catch (IOException e) {
+            log.error(e.getMessage());
+        }
+    }
+
+    private String getContentType(String path) {
+        return ContentType.findContentType(path).getValue();
+    }
+
+    private byte[] findBody(String contentType, String path) throws IOException {
+        return Files.readAllBytes(new File(ResponseBody.findResponseBody(contentType).getPath() + path).toPath());
+    }
+
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+    public void setHeader(String name, String value) {
+        headers.put(name, value);
+    }
+
+    private String getStatusCode(int status) {
+        if (status == HttpStatus.MOVED_TEMPORARILY.getValue()) {
+            return HttpStatus.MOVED_TEMPORARILY.getReason();
+        }
+
+        return HttpStatus.OK.getReason();
+    }
+
+    public String getResponse() {
+        return headers.getOrDefault("Location", "");
+    }
+}

리뷰: status와 header로 나누어 저장하는 것 좋네요!!
@@ -0,0 +1,81 @@
+package util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.Map;
+
+public class HttpResponse {
+
+    private Logger log = LoggerFactory.getLogger(getClass());
+    private int status;
+    private Map<String, String> headers = new HashMap<>();
+
+    public void processResponse(String path, HttpResponse response, OutputStream out) throws IOException {
+        String contentType = response.getContentType(path);
+        byte[] body = findBody(contentType, path);
+        DataOutputStream dos = new DataOutputStream(out);
+        responseHeader(dos, body.length, contentType);
+        responseBody(dos, body);
+    }
+
+
+    private void responseHeader(DataOutputStream dos, int lengthOfBodyContent, String contentType) {
+        try {
+            dos.writeBytes("HTTP/1.1 " + status + " " + getStatusCode(status) + "\r\n");
+            dos.writeBytes("Content-Type: " + contentType + "\r\n");
+            dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n");
+
+            for (Map.Entry<String, String> header : headers.entrySet()) {
+                dos.writeBytes(header.getKey() + ": " + header.getValue() + "\r\n");
+            }
+
+            dos.writeBytes("\r\n");
+        } catch (IOException e) {
+            log.error(e.getMessage());
+        }
+    }
+
+    private void responseBody(DataOutputStream dos, byte[] body) {
+        try {
+            dos.write(body, 0, body.length);
+            dos.flush();
+        } catch (IOException e) {
+            log.error(e.getMessage());
+        }
+    }
+
+    private String getContentType(String path) {
+        return ContentType.findContentType(path).getValue();
+    }
+
+    private byte[] findBody(String contentType, String path) throws IOException {
+        return Files.readAllBytes(new File(ResponseBody.findResponseBody(contentType).getPath() + path).toPath());
+    }
+
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+    public void setHeader(String name, String value) {
+        headers.put(name, value);
+    }
+
+    private String getStatusCode(int status) {
+        if (status == HttpStatus.MOVED_TEMPORARILY.getValue()) {
+            return HttpStatus.MOVED_TEMPORARILY.getReason();
+        }
+
+        return HttpStatus.OK.getReason();
+    }
+
+    public String getResponse() {
+        return headers.getOrDefault("Location", "");
+    }
+}

리뷰: 이 클래스에서 전체적으로 제가 구현하고 싶은 부분들을 잘 나누어주신것 같아요! 많이 배웠습니다
@@ -0,0 +1,81 @@
+package util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.util.HashMap;
+import java.util.Map;
+
+public class HttpResponse {
+
+    private Logger log = LoggerFactory.getLogger(getClass());
+    private int status;
+    private Map<String, String> headers = new HashMap<>();
+
+    public void processResponse(String path, HttpResponse response, OutputStream out) throws IOException {
+        String contentType = response.getContentType(path);
+        byte[] body = findBody(contentType, path);
+        DataOutputStream dos = new DataOutputStream(out);
+        responseHeader(dos, body.length, contentType);
+        responseBody(dos, body);
+    }
+
+
+    private void responseHeader(DataOutputStream dos, int lengthOfBodyContent, String contentType) {
+        try {
+            dos.writeBytes("HTTP/1.1 " + status + " " + getStatusCode(status) + "\r\n");
+            dos.writeBytes("Content-Type: " + contentType + "\r\n");
+            dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n");
+
+            for (Map.Entry<String, String> header : headers.entrySet()) {
+                dos.writeBytes(header.getKey() + ": " + header.getValue() + "\r\n");
+            }
+
+            dos.writeBytes("\r\n");
+        } catch (IOException e) {
+            log.error(e.getMessage());
+        }
+    }
+
+    private void responseBody(DataOutputStream dos, byte[] body) {
+        try {
+            dos.write(body, 0, body.length);
+            dos.flush();
+        } catch (IOException e) {
+            log.error(e.getMessage());
+        }
+    }
+
+    private String getContentType(String path) {
+        return ContentType.findContentType(path).getValue();
+    }
+
+    private byte[] findBody(String contentType, String path) throws IOException {
+        return Files.readAllBytes(new File(ResponseBody.findResponseBody(contentType).getPath() + path).toPath());
+    }
+
+    public void setStatus(int status) {
+        this.status = status;
+    }
+
+    public void setHeader(String name, String value) {
+        headers.put(name, value);
+    }
+
+    private String getStatusCode(int status) {
+        if (status == HttpStatus.MOVED_TEMPORARILY.getValue()) {
+            return HttpStatus.MOVED_TEMPORARILY.getReason();
+        }
+
+        return HttpStatus.OK.getReason();
+    }
+
+    public String getResponse() {
+        return headers.getOrDefault("Location", "");
+    }
+}

리뷰: `headers` 를 이용해서 더 리팩토링 할 수 있을 것 같아요.
@@ -0,0 +1,56 @@
+package util;
+
+public class HttpRequest {
+
+    private String method;
+    private String url;
+    private String queryString;
+
+    public HttpRequest(String line) {
+        String[] splitHeader = line.split(" ");
+        // uriPath = 전체 uri (쿼리 파라미터 분리 전)
+        String uriPath = getURIPath(splitHeader);
+
+        // 쿼리 파라미터 분리 후 url
+        this.url = getPath(uriPath);
+        this.method = splitHeader[0];
+        this.queryString = getQueryParameters(uriPath);
+    }
+
+    public String getMethod() {
+        return method;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public String getQueryString() {
+        return queryString;
+    }
+
+    @Override
+    public String toString() {
+        return "HttpRequest{" +
+                "method='" + method + '\'' +
+                ", url='" + url + '\'' +
+                ", queryString='" + queryString + '\'' +
+                '}';
+    }
+
+    private String getURIPath(String[] splitHeader) {
+        return splitHeader[1];
+    }
+
+    private String getPath(String uriPath) {
+        return uriPath.split("\\?")[0];
+    }
+
+    private String getQueryParameters(String uriPath) {
+        String[] split = uriPath.split("\\?");
+        if (split.length > 1) {
+            return split[1];
+        }
+        return "";
+    }
+}

리뷰: inline으로 줄여보는 건어떨까요? 의미를 드러내는 지역변수가 아니라면 생략하는 편이 깔끔한 거같아요.
@@ -0,0 +1,45 @@
+package controller;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import service.UserJoinService;
+import util.HttpRequest;
+import util.HttpResponse;
+
+public class UserController {
+    private final String HTTP_GET = "GET";
+    private final String JOIN_FORM = "/user/form.html";
+    private final String CREATE_USER_URL = "/user/create";
+    private UserJoinService userJoinService;
+    private Logger log = LoggerFactory.getLogger(getClass());
+
+    public UserController(UserJoinService userJoinService) {
+        this.userJoinService = userJoinService;
+    }
+
+    // TODO : 에러페이지 생성, 회원가입 검증
+    public String process(HttpRequest request, HttpResponse response) {
+        // GET 요청인 경우 분리
+        if (request.getMethod().equals(HTTP_GET)) {
+            // 회원 가입 폼 보여주기
+            if (request.getUrl().equals(JOIN_FORM)) {
+                return JOIN_FORM;
+            }
+            // 회원가입일 경우
+            if (request.getUrl().equals(CREATE_USER_URL)) {
+                return addUser(request.getQueryString(), response);
+            }
+        }
+
+        return "/error";
+    }
+
+    private String addUser(String queryParameters, HttpResponse response) {
+        userJoinService.addUser(queryParameters);
+
+        response.setStatus(302);
+        response.setHeader("Location", "/index.html");
+        return response.getResponse();
+    }
+
+}

리뷰: 상수가 많아지면 좀 헷갈릴거같아서, 시그니처에 규칙같은게 있으면 좋겠네요
@@ -1,13 +1,16 @@
 package kr.codesquad.baseball.dto;
 
-import lombok.AllArgsConstructor;
 import lombok.Getter;
-import lombok.NoArgsConstructor;
 import lombok.Setter;
 
 @Getter @Setter
-@AllArgsConstructor @NoArgsConstructor
 public class GameInitializingRequestDto {
 
     private Integer matchId;
+
+    public GameInitializingRequestDto() {}
+
+    public GameInitializingRequestDto(Integer matchId) {
+        this.matchId = matchId;
+    }
 }

리뷰: Lombok 사용에 대해서 조금 꺼려지시는 면이 있는 것 같은데 lombok 이제 쓰셔도 괜찮아요. 
다만 공통적으로 주의해야 할 사항들이 있는데, 아래 링크를 참고해 주세요. 

https://kwonnam.pe.kr/wiki/java/lombok/pitfall
@@ -1,13 +1,10 @@
 package kr.codesquad.baseball.dto.teamVO;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.Setter;
 
 @Getter @Setter
-@AllArgsConstructor
 public class TeamVO {
 
     @JsonIgnore
@@ -19,4 +16,13 @@ public class TeamVO {
 
     @JsonIgnore
     private int score;
+
+    public TeamVO() {}
+
+    public TeamVO(Integer teamId, String teamName, int totalScore, int score) {
+        this.teamId = teamId;
+        this.teamName = teamName;
+        this.totalScore = totalScore;
+        this.score = score;
+    }
 }

리뷰: `VO`, `DTO`, 그리고 모델 클래스를 어떤 기준으로 구분하셨나요?
@@ -1,13 +1,16 @@
 package kr.codesquad.baseball.dto;
 
-import lombok.AllArgsConstructor;
 import lombok.Getter;
-import lombok.NoArgsConstructor;
 import lombok.Setter;
 
 @Getter @Setter
-@AllArgsConstructor @NoArgsConstructor
 public class GameInitializingRequestDto {
 
     private Integer matchId;
+
+    public GameInitializingRequestDto() {}
+
+    public GameInitializingRequestDto(Integer matchId) {
+        this.matchId = matchId;
+    }
 }

리뷰: 이전부터 롬복을 아무 생각 없이 기계적으로 사용 했던거 같습니다. 지난 프로젝트에 빌더를 써보면서 더더욱 롬복 없이 구현을 해봐야겠다는 생각이 들어서 페어에게 쓰지 말자고 제안했고, 이번 프로젝트에는 클래스에 빌더를 직접 만들어보고 있는데 공부가 많이 되고 있네요.
알려주신 주의사항 링크도 읽어 봤는데 모르고 쓴게 참 많았다는 생각이 드네요! 다음 프로젝트부터 유의하며 사용 하겠습니다. 조언 해주셔서 감사합니다.
@@ -1,13 +1,10 @@
 package kr.codesquad.baseball.dto.teamVO;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.Setter;
 
 @Getter @Setter
-@AllArgsConstructor
 public class TeamVO {
 
     @JsonIgnore
@@ -19,4 +16,13 @@ public class TeamVO {
 
     @JsonIgnore
     private int score;
+
+    public TeamVO() {}
+
+    public TeamVO(Integer teamId, String teamName, int totalScore, int score) {
+        this.teamId = teamId;
+        this.teamName = teamName;
+        this.totalScore = totalScore;
+        this.score = score;
+    }
 }

리뷰: 모델 클래스는 DB의 엔터티와 직접 대응되는 클래스라 생각 했고, VO는 DB의 여러 엔터티 데이터를 DTO에 알맞게 가공한 최소 단위(DTO의 부분 집합), DTO는 클라이언트와 통신을 하는 접점에서 사용되는 최종 데이터 클래스라는 기준을 세우고 사용을 했었습니다.
백엔드 요구 사항인(옵션) 팀, 선수 데이터 관리 툴을 염두에 두고 분류를 했던건데, 로직이 복잡해지다 보니 VO와 모델 사이의 경계가 많이 모호해진거 같습니다ㅜㅜ
이런 경우에 VO라는 약어를 사용하는게 맞는건지 애매한 점이 있었는데, 아무래도 더 공부하고 생각을 해봐야 할거 같습니다. 조언 해주신 것처럼 학습을 더 해보겠습니다!
@@ -0,0 +1,48 @@
+/* http://meyerweb.com/eric/tools/css/reset/
+   v2.0 | 20110126
+   License: none (public domain)
+*/
+
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+	margin: 0;
+	padding: 0;
+	border: 0;
+	font-size: 100%;
+	font: inherit;
+	vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+	display: block;
+}
+body {
+	line-height: 1;
+}
+ol, ul {
+	list-style: none;
+}
+blockquote, q {
+	quotes: none;
+}
+blockquote:before, blockquote:after,
+q:before, q:after {
+	content: '';
+	content: none;
+}
+table {
+	border-collapse: collapse;
+	border-spacing: 0;
+}

리뷰: css 리셋 잊고 있었는데 리마인드하고 갑니다!