ewhk9887/korean_code_reviews_from_github huggingface dataset:
@@ -0,0 +1,30 @@
+package codesquad.service;
+
+import codesquad.entity.QuestionEntity;
+import codesquad.repository.QuestionRepository;
+
+import java.util.List;
+
+public class QuestionServiceImpl implements QuestionService {
+    private final QuestionRepository questionRepository;
+
+    public QuestionServiceImpl(QuestionRepository questionRepository) {
+        this.questionRepository = questionRepository;
+    }
+
+    @Override
+    public void postQuestion(QuestionEntity questionEntity) {
+        questionRepository.post(questionEntity);
+        questionRepository.setBaseTime(questionEntity);
+    }
+
+    @Override
+    public List<QuestionEntity> findQuestions() {
+        return questionRepository.findAll();
+    }
+
+    @Override
+    public QuestionEntity findQuestion(String id) {
+        return questionRepository.findAll().get(Integer.parseInt(id) - 1);
+    }
+}

리뷰: Entity, Model, Dto, VO의 차이에 대해 알아보시면 좋을 것 같아요
@@ -0,0 +1,74 @@
+package codesquad.controller;
+
+import codesquad.AppConfig;
+import codesquad.dto.question.QuestionRequestDto;
+import codesquad.dto.question.QuestionResponseDto;
+import codesquad.entity.QuestionEntity;
+import codesquad.mapper.QuestionMapper;
+import codesquad.service.QuestionService;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Controller
+public class QuestionController {
+    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
+    QuestionService questionService = applicationContext.getBean("questionService", QuestionService.class);
+
+    @GetMapping("/questions/post")
+    public String getQuestionForm() {
+        return "qna/form";
+    }
+
+    @PostMapping("/questions")
+    public String postQuestion(QuestionRequestDto questionRequestDto) {
+        QuestionEntity questionEntity = QuestionMapper.dtoToEntity(questionRequestDto);
+        questionService.postQuestion(questionEntity);
+        return "redirect:/questions";
+    }
+
+    @GetMapping("/questions")
+    public String getQuestionList(Model model) {
+        List<QuestionResponseDto> questions = questionService.findQuestions().stream()
+                .map(questionEntity -> QuestionMapper.entityToDto(questionEntity))
+                .collect(Collectors.toList());
+
+        model.addAttribute("questions", questions);
+
+        return "qna/list";
+    }
+
+    @GetMapping("/questions/{id}")
+    public String getQuestionShow(@PathVariable String id, Model model) {
+        QuestionResponseDto question = new QuestionResponseDto(questionService.findQuestion(id));
+
+        model.addAttribute("writer", question.getWriter());
+        model.addAttribute("title", question.getTitle());
+        model.addAttribute("contents", question.getContents());
+        model.addAttribute("date", question.getDate());
+
+        return "qna/show";
+    }
+
+    @GetMapping("/")
+    public String getHome(Model model) {
+        List<QuestionEntity> questionEntityList = questionService.findQuestions();
+        if (questionEntityList.size() == 0) {
+            return "qna/list";
+        }
+
+        List<QuestionResponseDto> questionResponseDtoList = questionService.findQuestions().stream()
+                .map(questionEntity -> QuestionMapper.entityToDto(questionEntity))
+                .collect(Collectors.toList());
+
+        model.addAttribute("questions", questionResponseDtoList);
+        return "qna/list";
+    }
+}
\ No newline at end of file

리뷰: applicationcontext로부터 직접 빈을 가져오셔서 사용하신 이유가 궁금합니다!
@@ -1,18 +1,17 @@
 package codesquad.controller;
 
 import codesquad.AppConfig;
-import codesquad.dto.UserDto;
+import codesquad.dto.user.UserDto;
+import codesquad.dto.user.UserUpdateRequestDto;
 import codesquad.entity.UserEntity;
+import codesquad.mapper.UserMapper;
 import codesquad.service.UserService;
 import org.modelmapper.ModelMapper;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 import java.util.stream.Collectors;
@@ -39,7 +38,6 @@ public String registerUser(UserDto userDto) {
 
     @GetMapping()
     public String getUserList(Model model) {
-        System.out.println("userService.findUsers().get(0) = " + userService.findUsers().get(0));
         List<UserDto> users = userService.findUsers().stream()
                 .map(userEntity -> modelMapper.map(userEntity, UserDto.class)).collect(Collectors.toList());
         model.addAttribute("users", users);
@@ -57,4 +55,15 @@ public String getUserProfile(@PathVariable String userId, Model model) {
 
         return "user/profile";
     }
+
+    @GetMapping("/{userId}/form")
+    public String getProfileEditForm() {
+        return "user/update_form";
+    }
+
+    @PutMapping("/{userId}/update")
+    public String updateUserProfile(@PathVariable("userId") String userId, UserUpdateRequestDto requestDto) {
+        userService.updateUser(userId, UserMapper.dtoToEntity(requestDto));
+        return "redirect:/users";
+    }
 }

리뷰: 업데이트에는 보통 PUT과 PATCH가 사용됩니다. 이 둘의 차이는 무엇일까요?
@@ -1,22 +1,36 @@
 package codesquad;
 
-import codesquad.repository.ArrayUserRepository;
+import codesquad.repository.QuestionRepositoryImpl;
+import codesquad.repository.UserRepositoryImpl;
+import codesquad.repository.QuestionRepository;
 import codesquad.repository.UserRepository;
+import codesquad.service.QuestionService;
+import codesquad.service.QuestionServiceImpl;
 import codesquad.service.UserService;
 import codesquad.service.UserServiceImpl;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
 @Configuration
 public class AppConfig {
-
+    
     @Bean
     public UserService userService() {
         return new UserServiceImpl(userRepository());
     }
 
     @Bean
     public UserRepository userRepository() {
-        return new ArrayUserRepository();
+        return new UserRepositoryImpl();
+    }
+
+    @Bean
+    public QuestionService questionService() {
+        return new QuestionServiceImpl(questionRepository());
+    }
+
+    @Bean
+    public QuestionRepository questionRepository() {
+        return new QuestionRepositoryImpl();
     }
 }

리뷰: 우선 의존성을 주입하여 코드/객체 간의 결합도를 낮추기 위해 Service와 Repository는 자바 코드로 직접 스프링 빈을 등록하였습니다. 이는 개발을 진행하다 Repository를 변경해야하는 상황일 때, Config에 등록된 Repository Bean만 수정하면 되기 때문입니다. 

그럼 Controller의 역할을 생각해보겠습니다.
컨트롤러는 View와 Service를 이어주는 역할만 하고 비즈니스 로직을 가지고 있지 않습니다. 따라서 Repository가 변경되거나 비즈니스 로직이 변경되어도 Controller는 변경되지 않으므로 Config에서 등록하지 않았습니다.

ref: https://inf.run/SZEa -> 말 다듬는데 도움 받았습니다:)
@@ -0,0 +1,74 @@
+package codesquad.controller;
+
+import codesquad.AppConfig;
+import codesquad.dto.question.QuestionRequestDto;
+import codesquad.dto.question.QuestionResponseDto;
+import codesquad.entity.QuestionEntity;
+import codesquad.mapper.QuestionMapper;
+import codesquad.service.QuestionService;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Controller
+public class QuestionController {
+    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
+    QuestionService questionService = applicationContext.getBean("questionService", QuestionService.class);
+
+    @GetMapping("/questions/post")
+    public String getQuestionForm() {
+        return "qna/form";
+    }
+
+    @PostMapping("/questions")
+    public String postQuestion(QuestionRequestDto questionRequestDto) {
+        QuestionEntity questionEntity = QuestionMapper.dtoToEntity(questionRequestDto);
+        questionService.postQuestion(questionEntity);
+        return "redirect:/questions";
+    }
+
+    @GetMapping("/questions")
+    public String getQuestionList(Model model) {
+        List<QuestionResponseDto> questions = questionService.findQuestions().stream()
+                .map(questionEntity -> QuestionMapper.entityToDto(questionEntity))
+                .collect(Collectors.toList());
+
+        model.addAttribute("questions", questions);
+
+        return "qna/list";
+    }
+
+    @GetMapping("/questions/{id}")
+    public String getQuestionShow(@PathVariable String id, Model model) {
+        QuestionResponseDto question = new QuestionResponseDto(questionService.findQuestion(id));
+
+        model.addAttribute("writer", question.getWriter());
+        model.addAttribute("title", question.getTitle());
+        model.addAttribute("contents", question.getContents());
+        model.addAttribute("date", question.getDate());
+
+        return "qna/show";
+    }
+
+    @GetMapping("/")
+    public String getHome(Model model) {
+        List<QuestionEntity> questionEntityList = questionService.findQuestions();
+        if (questionEntityList.size() == 0) {
+            return "qna/list";
+        }
+
+        List<QuestionResponseDto> questionResponseDtoList = questionService.findQuestions().stream()
+                .map(questionEntity -> QuestionMapper.entityToDto(questionEntity))
+                .collect(Collectors.toList());
+
+        model.addAttribute("questions", questionResponseDtoList);
+        return "qna/list";
+    }
+}
\ No newline at end of file

리뷰: AppConfig에서 @ComponentScan 같은 Spring Bean을 자동으로 가져오기 위한 어노테이션을 사용하지 않았기에 직접 빈을 가져왔습니다!
(사실 질문 의도를 제대로 이해하지 못했습니다. 부연 설명 해주시면 감사하겠습니다!)
@@ -1,18 +1,17 @@
 package codesquad.controller;
 
 import codesquad.AppConfig;
-import codesquad.dto.UserDto;
+import codesquad.dto.user.UserDto;
+import codesquad.dto.user.UserUpdateRequestDto;
 import codesquad.entity.UserEntity;
+import codesquad.mapper.UserMapper;
 import codesquad.service.UserService;
 import org.modelmapper.ModelMapper;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
 import java.util.stream.Collectors;
@@ -39,7 +38,6 @@ public String registerUser(UserDto userDto) {
 
     @GetMapping()
     public String getUserList(Model model) {
-        System.out.println("userService.findUsers().get(0) = " + userService.findUsers().get(0));
         List<UserDto> users = userService.findUsers().stream()
                 .map(userEntity -> modelMapper.map(userEntity, UserDto.class)).collect(Collectors.toList());
         model.addAttribute("users", users);
@@ -57,4 +55,15 @@ public String getUserProfile(@PathVariable String userId, Model model) {
 
         return "user/profile";
     }
+
+    @GetMapping("/{userId}/form")
+    public String getProfileEditForm() {
+        return "user/update_form";
+    }
+
+    @PutMapping("/{userId}/update")
+    public String updateUserProfile(@PathVariable("userId") String userId, UserUpdateRequestDto requestDto) {
+        userService.updateUser(userId, UserMapper.dtoToEntity(requestDto));
+        return "redirect:/users";
+    }
 }

리뷰: `PUT`은 자원 전체를 교체하여, 자원의 모든 필드가 필요하고
`PATCH`는 자원의 부분만 교체하여, 자원의 일부 필드만 있어도 됩니다. 

GOOD
```
PUT /userId/1
{
    "userId" : "mywnajsldkf",
     "age" : 24
}

GET /userId/1
{    
     "userId" : "mywnajsldkf",
     "age" : 24
}    
```

BAD
```
PUT /userId/1
{
    "userId" : "mywnajsldkf",
}

GET /userId/1
{    
     "userId" : "mywnajsldkf",
     "age" : null
}
```

GOOD
```
PATCH /userId/1
{
    "userId" : "mywnajsldkf",
}

GET /userId/1
{    
     "userId" : "mywnajsldkf",
     "age" : 24
}
```
@@ -7,6 +7,8 @@
 public interface UserRepository {
     void register(UserEntity userEntity);
 
+    void update(String userId, UserEntity userEntity);
+
     UserEntity findById(String userId);
 
     List<UserEntity> findAll();

리뷰: dto <-> entity 사이의 맵핑을 어디서 해야할지 고민을 했는데요. 
DTO는 컨트롤러 레이어에 종속되어야 한다고 생각해 맵핑에 관련된 것은 모두 컨트롤러에서 두려고 하였습니다. 

update()에 대한 부분은 피드백을 보고 다시 보니, 새로운 userEntity를 생성하는 register와 다르게 기존에 있는 userEntity를 수정하는 것이다보니 값을 update하는 방향에 집중했습니다. 그러다보니 DTO -> Entity도 새롭게 객체를 만든다는 생각에 거치지 않았네요.😅 

다시보니 register() 처럼 controller에서 entity로 바꿔서 넘겨지고 entity에 있는 값들을 repository에서 꺼내어 업데이트하는 방식으로 수정하고 싶은데 @saint6839 님의 생각은 어떠세요?

+)
dto <-> entity는 어디에에 관한 부분은...
이전 리뷰에서도 질문드리기도 했고, 다양한 [토론글 1](https://okky.kr/articles/708060), [토론글 2](https://tecoble.techcourse.co.kr/post/2021-04-25-dto-layer-scope/) 등을 찾아보기도 했는데요~ 
스스로 내린 작업 방향성은 **repository까지 들어가지 말 것, 프로젝트 내에 일관성을 유지할 것, (무엇보다) 같이 하는 사람이랑 맞출 것** 입니다.🙂
이 부분에 대해 상엽님의 생각도 들어보고 싶네요~
@@ -0,0 +1,30 @@
+package codesquad.service;
+
+import codesquad.entity.QuestionEntity;
+import codesquad.repository.QuestionRepository;
+
+import java.util.List;
+
+public class QuestionServiceImpl implements QuestionService {
+    private final QuestionRepository questionRepository;
+
+    public QuestionServiceImpl(QuestionRepository questionRepository) {
+        this.questionRepository = questionRepository;
+    }
+
+    @Override
+    public void postQuestion(QuestionEntity questionEntity) {
+        questionRepository.post(questionEntity);
+        questionRepository.setBaseTime(questionEntity);
+    }
+
+    @Override
+    public List<QuestionEntity> findQuestions() {
+        return questionRepository.findAll();
+    }
+
+    @Override
+    public QuestionEntity findQuestion(String id) {
+        return questionRepository.findAll().get(Integer.parseInt(id) - 1);
+    }
+}

리뷰: > 엔티티를 이용해 데이터를 주고 받으면 어떤 문제가 있을지 고민해보시면 좋을 것 같습니다!

네! 한번 고민해보겠습니다~ 혹시 상엽님이 말씀하신 데이터를 주고 받는 부분은 view(controller)와 주고받는다는 말씀이실까요?
@@ -0,0 +1,30 @@
+package codesquad.service;
+
+import codesquad.entity.QuestionEntity;
+import codesquad.repository.QuestionRepository;
+
+import java.util.List;
+
+public class QuestionServiceImpl implements QuestionService {
+    private final QuestionRepository questionRepository;
+
+    public QuestionServiceImpl(QuestionRepository questionRepository) {
+        this.questionRepository = questionRepository;
+    }
+
+    @Override
+    public void postQuestion(QuestionEntity questionEntity) {
+        questionRepository.post(questionEntity);
+        questionRepository.setBaseTime(questionEntity);
+    }
+
+    @Override
+    public List<QuestionEntity> findQuestions() {
+        return questionRepository.findAll();
+    }
+
+    @Override
+    public QuestionEntity findQuestion(String id) {
+        return questionRepository.findAll().get(Integer.parseInt(id) - 1);
+    }
+}

리뷰: > Entity, Model, Dto, VO의 차이에 대해 알아보시면 좋을 것 같아요

조언 감사합니다~

공부하면서 궁금한 점이 있습니다. 

아직 VO를 사용하는 이유가 와닿지 않는데요~ 
DTO처럼 데이터를 전송하는 상황에만 쓴다는 것이 아닌,
VO의 제약사항(불변성, 동등성, 자가 유효성)이 있기에 
객체 생성 시 VO 그 자체가 제약사항이 되거나 인스턴스가 정해져 있는 경우 미리 인스턴스를 생성하는 등 
VO의 특징으로 얻을 수 있는 이점이 있기에 사용한다고 이해해도 될까요?

아래부터는 정리한 내용입니다.

# Entity
- DB의 테이블과 매핑되는 객체로, `id`를 통해 각각의 Entity를 구분합니다. 
- 로직을 가질 수 있습니다. 
```java
public class User {
   private Long id;
   private String name;
   private String email;
   
   @Builder
    public User(String name, String email) {
      this.name = name;
      this.email = email;
   }
   
   public User update(String name, String email) {
      this.name = name;
      this.email = email;
      return this;
   }
}
```

# DTO
- Data Transfer Object, 말 그대로 계층(Layer: Service, Controller, Repository)간 데이터 교환을 위해 사용하는 객체입니다. 
- 로직을 갖지 않고, getter/setter 메소드만 갖습니다. 
```java
class UserDto {
   private int name;
   private int email;
   
   public UserDto(int name, int email){
      this.name = name;
      this.email = email;
   }
   
   public int getName() {
       return name;
   }
   
   public int setName(int name) {
      this.name = name;
   }
   ...
}
```

# VO
Value Object의 약자로 값 그 자체입니다. 
사용 시, 염두해야할 부분은 **1. equals & hash code 메서드를 재정의해야 한다. 2. 수정자(setter)가 없는 불변 객체여야 한다.** 입니다. 
1번에 대해 좀 더 이야기하자면 동등성을 갖기 때문에 객체가 실제 다른 객체이더라도, 논리적으로 값이 같다면(나의 아이폰 13미니, 너의 휴대폰 13미니 서로 다르지만 같음) 같다고 말합니다. 
2번은 setter가 없어서 값 변경 걱정이 없어 DB에서 값을 가져와 데이터를 VO에 담으면 항상 VO의 값을 원본으로 신뢰할 수 있습니다.

+) 잘 정리된 글도 첨부합니다. 
* https://tecoble.techcourse.co.kr/post/2020-06-11-value-object/
* https://hudi.blog/value-object/

# Model
Model은 비즈니스 로직에서 발생하는 값이라고 생각합니다. 
DB에 값을 넣거나 가져오는 것이 아닌 중간에 연산이 이루어질 때 필드들을 모델에 담아 관리한다고 생각합니다.
@@ -1,22 +1,36 @@
 package codesquad;
 
-import codesquad.repository.ArrayUserRepository;
+import codesquad.repository.QuestionRepositoryImpl;
+import codesquad.repository.UserRepositoryImpl;
+import codesquad.repository.QuestionRepository;
 import codesquad.repository.UserRepository;
+import codesquad.service.QuestionService;
+import codesquad.service.QuestionServiceImpl;
 import codesquad.service.UserService;
 import codesquad.service.UserServiceImpl;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
 @Configuration
 public class AppConfig {
-
+    
     @Bean
     public UserService userService() {
         return new UserServiceImpl(userRepository());
     }
 
     @Bean
     public UserRepository userRepository() {
-        return new ArrayUserRepository();
+        return new UserRepositoryImpl();
+    }
+
+    @Bean
+    public QuestionService questionService() {
+        return new QuestionServiceImpl(questionRepository());
+    }
+
+    @Bean
+    public QuestionRepository questionRepository() {
+        return new QuestionRepositoryImpl();
     }
 }

리뷰: 의존성 주입은 스프링이 알아서 해주는 부분입니다 ~
스프링 부트의 DI 방식에 대해 알아보면 좋을 것 같아요
@@ -0,0 +1,74 @@
+package codesquad.controller;
+
+import codesquad.AppConfig;
+import codesquad.dto.question.QuestionRequestDto;
+import codesquad.dto.question.QuestionResponseDto;
+import codesquad.entity.QuestionEntity;
+import codesquad.mapper.QuestionMapper;
+import codesquad.service.QuestionService;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Controller
+public class QuestionController {
+    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
+    QuestionService questionService = applicationContext.getBean("questionService", QuestionService.class);
+
+    @GetMapping("/questions/post")
+    public String getQuestionForm() {
+        return "qna/form";
+    }
+
+    @PostMapping("/questions")
+    public String postQuestion(QuestionRequestDto questionRequestDto) {
+        QuestionEntity questionEntity = QuestionMapper.dtoToEntity(questionRequestDto);
+        questionService.postQuestion(questionEntity);
+        return "redirect:/questions";
+    }
+
+    @GetMapping("/questions")
+    public String getQuestionList(Model model) {
+        List<QuestionResponseDto> questions = questionService.findQuestions().stream()
+                .map(questionEntity -> QuestionMapper.entityToDto(questionEntity))
+                .collect(Collectors.toList());
+
+        model.addAttribute("questions", questions);
+
+        return "qna/list";
+    }
+
+    @GetMapping("/questions/{id}")
+    public String getQuestionShow(@PathVariable String id, Model model) {
+        QuestionResponseDto question = new QuestionResponseDto(questionService.findQuestion(id));
+
+        model.addAttribute("writer", question.getWriter());
+        model.addAttribute("title", question.getTitle());
+        model.addAttribute("contents", question.getContents());
+        model.addAttribute("date", question.getDate());
+
+        return "qna/show";
+    }
+
+    @GetMapping("/")
+    public String getHome(Model model) {
+        List<QuestionEntity> questionEntityList = questionService.findQuestions();
+        if (questionEntityList.size() == 0) {
+            return "qna/list";
+        }
+
+        List<QuestionResponseDto> questionResponseDtoList = questionService.findQuestions().stream()
+                .map(questionEntity -> QuestionMapper.entityToDto(questionEntity))
+                .collect(Collectors.toList());
+
+        model.addAttribute("questions", questionResponseDtoList);
+        return "qna/list";
+    }
+}
\ No newline at end of file

리뷰: 스프링부트에서 생성자 주입을 하는 방법에 대해 검색해보시면 좋을 것 같아요
@@ -0,0 +1,45 @@
+package codesquad.mapper;
+
+import codesquad.dto.question.QuestionRequestDto;
+import codesquad.dto.question.QuestionResponseDto;
+import codesquad.entity.QuestionEntity;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+public class QuestionMapper {
+
+    public static QuestionEntity dtoToEntity(QuestionRequestDto questionRequestDto) {
+        if (questionRequestDto == null){
+            return null;
+        }
+
+        QuestionEntity.QuestionEntityBuilder questionEntity = QuestionEntity.builder();
+
+        questionEntity.writer(questionRequestDto.getWriter());
+        questionEntity.title(questionRequestDto.getTitle());
+        questionEntity.contents(questionRequestDto.getContents());
+
+        return questionEntity.build();
+    }
+
+    public static QuestionResponseDto entityToDto(QuestionEntity questionEntity) {
+        if (questionEntity == null) {
+            return null;
+        }
+
+        QuestionResponseDto.QuestionResponseDtoBuilder questionResponseDto = QuestionResponseDto.builder();
+
+        questionResponseDto.writer(questionEntity.getWriter());
+        questionResponseDto.title(questionEntity.getTitle());
+        questionResponseDto.contents(questionEntity.getContents());
+        questionResponseDto.date(localTimeToString(questionEntity.getCreatedDate()));
+
+        return questionResponseDto.build();
+    }
+
+    public static String localTimeToString(LocalDateTime localDateTime) {
+        String stringLocalTime = localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
+        return stringLocalTime;
+    }
+}

리뷰: 변수는 private 으로 선언하고 setter 를 사용해서 접근하는게 자바의 일반적인 원칙입니다 ~
@@ -0,0 +1,24 @@
+package codesquad.entity;
+
+import lombok.*;
+
+@Setter
+@Getter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class QuestionEntity extends BaseTimeEntity {
+
+    private String writer;
+    private String title;
+    private String contents;
+
+    @Override
+    public String toString() {
+        return "QuestionEntity{" +
+                "writer='" + writer + '\'' +
+                ", title='" + title + '\'' +
+                ", contents='" + contents + '\'' +
+                '}';
+    }
+}

리뷰: Entity 라는 postfix 를 붙이지 않아도 될 것 같습니다 ~