2022. 3. 22. 22:10ใProgramming Project ์์ ์ค/๋ด์ฉ ์ ๋ฆฌ
๐ง๐ป๐ป Git Hub ์ฃผ์
๐ ๋ชฉ์ฐจ
โ [BackEnd][Maven-PJ] ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ๊ฒ์ํ ๋ง๋ค๊ธฐ : ๋ชฉ๋ก ์กฐํ
โ [BackEnd][Maven-PJ]๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ๊ฒ์ํ ๋ง๋ค๊ธฐ : ์์ธ ์กฐํ
โ [BackEnd][Maven-PJ]๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ๊ฒ์ํ ๋ง๋ค๊ธฐ : ์ญ์
โ [BackEnd][Maven-PJ] ์ฌ๋ด ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ๊ฒ์ํ : ๋ต๋ณ ๋ฑ๋ก / ์์
โ [BackEnd][Maven-PJ] ์ฌ๋ด ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ๊ฒ์ํ : ๋ต๋ณ ์ญ์
๐จ๐ฉ๐ง๐ฆ ํ์ ๊ด๋ จ
โ [BackEnd][Maven-PJ] ์ฌ๋ด ๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ํ์ ๊ด๋ จ : ํ์ ๊ฐ์
๐๋ถ ๋ก
โ [BackEnd][Maven-PJ]๊ฐ๋ฐ์ ์ปค๋ฎค๋ํฐ ์๋น์ค - ๊ฒ์ํ ๋ง๋ค๊ธฐ : Paging์ฒ๋ฆฌ
๐ค ๋ด๊ฐ ๋ง๋ Exception
โ [Exception ์ ๋ฆฌ] org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)
โ [Vue.js][Spring] Post Data ์ ์ก ๊ฐ null๊ฐ ์ ์ก ๋ฌธ์
โ
๐ ๋ต๋ณ ๋ง๋ค๊ธฐ - ๋ฑ๋ก / ์์
๐ฝ Source Code
๐ฆ DevInquryReplyVO.java
์ด VO๋ ๊ฒ์ํ VO์์ ๊ผญ ํ์ํ ์ผ๋ถ๋ง ๋ฐ๋ก ์ ์๋ฅผ ํด ๋ ๊ฒ์ด์์.
์ธ๋ฐ์์ด ์ฌ๋ฌ ๊ฐ์ง๋ฅผ ์ ์ ํด ๋์ผ๋ฉด Front End์ Data๋ฅผ ์ฃผ๊ณ ๋ฐ์ ๋, ๋ณด์ ์ทจ์ฝ์ ์ด ์๊ธธ ์๋ ์๊ณ , ์ฑ๋ฅ Issue๋ ๋ฐ์ํ ์ ์๊ธฐ ๋๋ฌธ์ธ ๊ฒ์ด์์.
๐ฝ Code ๋ถ์
๐ฆ DevInquryReplyController.java
28๋ฒ์งธ ์ค์๋ ๋ ๊ฐ์ Annotion์ ์ ์ธ์ ํ๋๋ฐ ์ฒซ๋ฒ์งธ `RequiredArgsConstuctor`๋ fina๋ก ์ง์ ๋ Member ๋ณ์์ ์์ฑ์๋ฅผ ์๋์ผ๋ก ๋ง๋ค์ด ์ฃผ๊ณ , DIํด ์ฃผ๋ Annotaion์ธ ๊ฒ์ด์์.
๋๋ฒ์งธ `Sl4j`๋ Console์ฐฝ์ Log๋ฅผ ์ฐ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๊ฒ์ธ๋ฐ, `System.out.println()`์ ๊ฒฝ์ฐ ์ฑ๋ฅ๋ฉด์์ ์ฌ์ฉํ๋ ๊ฒ์ ๋ํด ๋จ์ ์ด ๋ง๊ธฐ ๋๋ฌธ์ ์ค์ ๋ก Application ๊ฐ๋ฐ ์์๋ ์ ์ฌ์ฉํ์ง ์๋ ๊ฒ์ด์์.
29 ~ 30๋ฒ์งธ ์ค์ ์๋ Annotaion์ Swagger์ ํด๋นํ๋ ๊ฒ์ธ๋ฐ, ์ด๊ฑด ์ฐจํ ๋ฐ๋ก ์ ๋ฆฌ๋ฅผ ํ๋๋ก ํ ๊ฒ์ด์์.
๊ทธ๋ฆฌ๊ณ , 31๋ฒ์งธ ์ค์ `RestController`๋ผ๋ Annotion์ ์ฌ์ฉํ ๊ฒ์ด์์.
43๋ฒ์งธ ์ค์ ๋จผ์ Map์ ํ๋ ๋ง๋ค์ด ์ฃผ๋๋ฐ, Key๋ ๋ฌธ์์ด๋ก ๋ฐ๊ณ , ๊ฐ์ ๊ฐ์ฒด(Object)๋ก ๋ฐ๋๋ก ํ๋ result๋ผ๋ Map์ ๋ง๋ค์ด ์ค ๊ฒ์ด์์. ์ด๊ฒ์ ๋ง๋๋ ์ด์ ๋ 53๋ฒ์งธ ์ค์ ๋ณด์๋ฉด ์์๊ฒ ์ง๋ง, ๊ฒฐ๊ณผ๊ฐ์ Returnํ ๋, ๋ด๊ณ ์ ํ๋ ๋ด์ฉ์ ๋ด๊ธฐ ์ํจ์ด์์.
๊ทธ๋์ ํด๋น Method์ ๋ฐํ Type์ Object๋ก ํด ์ค ๊ฒ์ด์์.
์ด ์น๊ตฌํํ
๋ Front End๊ฐ ์์ฒญ์ ๋ณด๋ผ ๋, ์ด๋ค ๊ฒ์๊ธ์ ๋ต๋ณ์ธ์ง๋ฅผ ์ ์ ์๋๋ก ๊ฒ์๊ธ ์ผ๋ จ๋ฒํธ(inqrySn)์ ๋ต๋ณ ์ฌ๋ถ(answerAt), ๊ทธ๋ฆฌ๊ณ , ์ ์ผ ์ค์ํ ๋ต๋ณ์ ๋ํ ๋ด์ฉ์ด ๋ค์ด๊ฐ ๋ต๋ณ ๋ด์ฉ(answerCn), ๊ทธ๋ฆฌ๊ณ , ๋ต๋ณ์ ๋๊ฐ ์ ์๋์ง๋ฅผ ํ์ํด ์ฃผ๊ธฐ ์ํด ๋ต๋ณ ์์ฑ์(answerUserSn)๊ณผ ์ธ์ ์์ฑ๋์๋์ง๋ฅผ ์๊ธฐ ์ํ ๋ต๋ณ ์์ฑ์ผ(answerDt)๋ฅผ ๋ฐ๋ DevInquryReplyVO ๊ฐ์ฒด๋ฅผ ๋ฐ์ ๊ฒ์ด์์.
Controller์ ํ๋ ์ผ์ ๋จ์ํด์ผ ํ๋ ๊ฒ์ด์์. Route ๊ธฐ๋ฅ์ ๋ด๋นํ๊ธฐ ๋๋ฌธ์ ๋น์ฆ๋์ค ๋ก์ง์ ๋ด๋นํ๋ Service์ ๋ณธ๊ฒฉ์ ์ธ ์ ๋ฌด ์ฒ๋ฆฌ๋ฅผ ๋งก๊ธธ ๊ฒ์ด์์.
์ค! ์ ๊ทธ๋๋ 49๋ฒ์งธ ์ค์ `devInquryReplyService.devInquryReplyRegist();`๋ฅผ ํธ์ถํ๋๋ฐ, ๋งค๊ฐ ๋ณ์๋ก devInquryReplyVO ๊ฐ์ฒด๋ฅผ ์ ๋ฌํ๊ณ ์๋ ๊ฒ์ด์์. ๊ทธ๋ผ Service๋ฅผ ๋ง๋๋ฌ ๊ฐ๋ด์ผ๊ฒ ์ด์!
๐ฆ DevInquryReplyService.java
์์ Code๋ Interface๋ก ๊ตฌํ์ด ๋์ด ์๋ ๊ฒ์ด์์. Service๋ฅผ Interface์ ๊ตฌํ์ฒด(Implement)๋ก ๋๋๋ ์ด์ ๋ ๊ฐ์ฒด ์์กด ๊ด๊ณ ๋๋ฌธ์ธ ๊ฒ์ด์์.
์ด ๊ณณ์์๋ ์ถ์ Method๋ง ๋ง๋ค์ด ์ฃผ๋ ๊ฒ์ด๋๋๋ค.
๐ฆ DevInquryReplyServiceImpl.java
์ด ๊ณณ์์๋ @Transational๋ ๋ณด์ด๊ณ , @Service๋ ๋ณด์ด๋ค์.
๊ทธ๋ฆฌ๊ณ , DevInquryReplyMapper๋ผ๋ final Member ๋ณ์๋ฅผ DIํ๊ธฐ ์ํด @RequiredArgsConstructor๋ ์ด์ฉํ ๊ฒ์ด์์.
/**
* ๊ฒ์๊ธ ๋ฑ๋ก
* @param devInquryReplyVO ๋ต๊ธ ๋ฑ๋ก ์ ๋ด์ฉ์ ๋ด์ Value Object
*/
@Override
public Object devInquryReplyRegist(DevInquryReplyVO devInquryReplyVO) {
log.info("DevInquryReplyService๋ฅผ ๊ตฌํํ DevInquryReplyServiceImpl์ devInquryReplyRegist(DevInquryReplyVO devInquryReplyVO)๊ฐ ํธ์ถ ๋์์ต๋๋ค!");
Map<String, Object> result = new HashMap<>();
try {
log.info("๋ต๋ณ ๋ด์ฉ์ด NULL์ด ์๋์ง ํ์ธ ํ๊ฒ ์ต๋๋ค!");
if (devInquryReplyVO.getAnswerCn() == null || Objects.equals(devInquryReplyVO.getAnswerDt(), "")) {
log.info("๋ต๋ณ ๋ด์ฉ์ด NULL ์
๋๋ค!");
result.put("code", 400);
result.put("message", "Bad Request / ๋ต๋ณ ๋ด์ฉ์ด NULL ์
๋๋ค.");
log.info("400 Code์ ํจ๊ป \"Bad Request / ๋ต๋ณ ๋ด์ฉ์ด NULL ์
๋๋ค.\" ๋ฐํํ๊ฒ ์ต๋๋ค!");
return result;
} // if (devInquryReplyVO.getAnswerCn() == null || Objects.equals(devInquryReplyVO.getAnswerDt(), "")) ๋
log.info("๋ต๋ณ ๋ด์ฉ ๋ฑ๋ก์ ์ํด ์ต์ด ๋ต๋ณ ์ฌ๋ถ(answerAt)์ true๋ก ๋ณ๊ฒฝํ๊ฒ ์ต๋๋ค!");
// devInquryReplyVO.setAnswerAt("Y");
// TODO - ํ์๊ฐ์
๋ฐ ๋ก๊ทธ์ธ ๋ก์ง ๊ตฌํ ๋ค ์๋ ํ๋์ฝ๋ฉ ์์ ํ์
log.info("๋ต๊ธ ์์ฑ์์ ๋ํ ๋ด์ฉ์ VO์ ์
๋ ฅํ๊ฒ ์ต๋๋ค!");
devInquryReplyVO.setAnswerUserSn(1);
log.info("devInquryReplyMapper์ devInquryReplyRegist(devInquryReplyVO)๋ฅผ ํธ์ถ ํ๊ฒ ์ต๋๋ค!");
devInquryReplyMapper.devInquryReplyRegist(devInquryReplyVO);
result.put("code", 201);
result.put("message", "๋ต๊ธ ๋ฑ๋ก ์ฑ๊ณต!");
result.put("resultSn", devInquryReplyVO.getInqrySn());
return result;
} catch (Exception e) {
log.warn("๋ต๊ธ ๋ฑ๋ก ์ค ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ฌ Catch์ ์ด ๋์ํ์์ต๋๋ค!");
e.printStackTrace();
log.warn(e.getMessage());
result.put("code", 500);
return result;
} // try-catch ๋
} // devInquryReplyRegist(DevInquryReplyVO devInquryReplyVO) ๋
์ค์ง์ ์ผ๋ก ์ด ๊ณณ์์ ํ์ํ Logic์ ์ฒ๋ฆฌํ๊ณ , DB์ ๋ณด๋ผ ๋ด์ฉ๋ค์ ์ ๋ฆฌํด์ Mapper๋ฅผ ํตํด MyBatis๋ก DB์ Query๋ฅผ ๋ ๋ ค์ฃผ๊ณ , ๊ทธ ๋ฐํ๊ฐ์ ๊ฐ๊ณตํด์ ์ ๋ฌ ํด ์ฃผ๋ ๊ณณ์ด์์.
๋จผ์ try ๋ฌธ ๋ถํฐ ๋ถ์ํด ๋ณด๋๋ก ํ ๊ฒ์ด์์.
48๋ฒ์งธ ์ค์ ๋ต๋ณ ๋ด์ฉ(answerCn)์ด null์ด๊ฑฐ๋, ๊ณต๋ฐฑ์ธ์ง๋ฅผ ํ์ธํ๋ ๊ฒ์ด์์.
๋ง์ฝ Null์ด๋ผ๋ฉด ๊ตณ์ด DB๋ฅผ ์ด์ฉํ ํ์๊ฐ ์๊ณ , ๋ต๋ณ์ ์ ์ฅํ ํ์๊ฐ ์์ผ๋ 400 Error (Bad Request)๋ฅผ ํตํด Client์๊ฒ '์๋ชป๋ ์์ฒญ์ ์ฃผ์ จ์ต๋๋ค!' ๋ผ๊ณ ์๋ฆฌ๊ธฐ ์ํด 52, 53๋ฒ์งธ ์ค์ ์์ ์ ํ ๊ฒ์ด๊ณ , ๊ทธ ๋ด์ฉ์ ๋ด์ result Map์ ๋ฐํ ํด ์ฃผ๋ ๊ฒ์ด์์.
Null์ด ์๋๋ผ๋ฉด 66๋ฒ์งธ ์ค์ ํ์ฌ ํ์ ๊ด๋ จ Logic์ด ๊ตฌํ๋์ง ์์์ผ๋ฏ๋ก, ์์๋ก ๋ต๋ณ ์์ฑ์ ์ ๋ณด๋ฅผ ๋ฃ์ด์ฃผ๊ธฐ ์ํด setter๋ฅผ ์ด์ฉํด์ ์ด์ฉ์ ์ ๋ณด๋ฅผ ๋ฃ์ด์ฃผ๊ณ , 69๋ฒ์งธ ์ค์ ๋ณธ๊ฒฉ์ ์ผ๋ก Mapper์ ํด๋น Method๋ฅผ ๋ถ๋ฌ VO ๊ฐ์ฒด๋ฅผ ๋๊ฒจ์ฃผ๋ฉด์ DB ์ฒ๋ฆฌ๋ฅผ ๋ถํํ๋ ๊ฒ์ด์์.
์ ์์ ์ผ๋ก ๋ฑ๋ก์ด ๋์๋ค๋ฉด HTTP Status Code 201(Create)๋ฅผ ๋ฐํํ๊ธฐ ์ํด ๋ด์ฉ์ ๋ฃ์ด์ฃผ๊ณ , ๋ต๋ณ์ด ๋ฌ๋ฆฐ ํด๋น ๊ฒ์๋ฌผ ๋ฒํธ๋ฅผ ํจ๊ป ์ ๋ฌ ํด ์ฃผ๊ธฐ ์ํด result์ ๋ด๊ณ , 75๋ฒ์งธ ์ค์ ๋ฐํ์ ํด ์ฃผ๋ ๊ฒ์ด์์.
๐ฆ DevInquryReplyMapper.java
@Mapper๋ฅผ ํตํด์ ์ด Class๊ณผ ์ฐ๊ฒฐ๋ ๊ตฌํ xml File๊ณผ ์ฐ๊ฒฐ์ ํด ์ค ๊ฒ์ด๊ณ , @Repository๋ฅผ ์ด์ฉํด์ ํด๋น Interface๊ฐ Repository์ด๋ผ๊ณ ์๋ ค์ฃผ๋ฉด์ DI๋ฅผ Spring์๊ฒ ๋งก๊ธธ ๊ฒ์ด์์.
๐ฆ ReplyMapper.xml
์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก DB์๊ฒ ๋ ๋ ค์ค Query๋ฅผ ์์ฑํ๋ Mapper.xml์ ๋ง๋๋ฌ ์จ ๊ฒ์ด์์.
3๋ฒ์งธ ์ค์ ๋ณด๋ฉด ์ด Mapper Interface๋ฅผ Mapping ํด ๋ฌ๋ผ๊ณ ํ๋ ๊ฒ์ธ๋ฐ, ์ ๋ ๊ฒฝ๋ก๋ก ์ ๋ ฅ์ ํด์ฃผ์ด์ผ ํ๋ ๊ฒ์ด์์.
Table ์ ๊ทํ๋ ์ฐจ ํ ์งํํ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ 6๋ฒ์งธ ์ค์ ๋ฌด์ํ์ ๋ ์ข์ ๊ฒ์ด์์.๐
์ฌ๋ฌ๋ถ์ ์ง๊ธ ๋ต๋ณ ๋ฑ๋ก์ด๋ผ๋ ๋ด์ฉ์ ๋ํด ๋ณด๊ณ ๊ณ์๋๋ฐ, SQL ๋ด์ฉ์ ๋ณด๋ฉด Update๋ฅผ ๋ ๋ฆฌ๊ณ ์๋ ๊ฒ์ ๋ณผ ์ ์๋ ๊ฒ์ด์์. ์ฃผ๋ํ๋์ด ์ ๊ทํ ๋ถ๋์ด๋ผ๊ณ ํ๋ ์ด์ ๊ฐ ๋ฐ๋ก ์ด๊ฒ์ธ๋ฐ,
์ด Table์ด Q&A ๊ฒ์ํ๊ณผ ๋ต๋ณ์ด ๋ชจ๋ ์ด์ฉํ๋ Table์ธ ๊ฒ์ด์์.
create๋ฅผ ์ฌ์ฉํ ์ ์๋ ๊ฒ์ ๊ฒ์๊ธ ์ ๋ชฉ(INQRY_SJ), ๊ฒ์๊ธ ๋ด์ฉ(INQRY_CN)๋ฑ์ด Not Null์ ํ์ฉํ์ง ์๊ณ ์๊ธฐ ๋๋ฌธ์ ๋ต๋ณ์ create๋ก ํ๊ฒ ๋๋ฉด Not Null ์ ์ฑ ์ ์ํด DB์ INSEART๋ฅผ ํ ์ ์๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ด์์.
๊ทธ๋์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ด์ฉ ์ ์์ด UPDATE๋ฅผ ์ด์ฉํ ๊ฒ์ด๋๋๋ค.
๋ํ ์ด๋ฌํ ์ด์ ๋ก ์ธํด ๋ฑ๋ก๊ณผ ์์ ์ด ํจ๊ป ์๋ ๊ฒ์ด์์.
์์ SQL ๋ฌธ์ ๋ณด๋ฉด ์ ์ ์๋ฏ์ด ๊ฒ์๊ธ ์ผ๋ จ๋ฒํธ(inqrySn)์ ํด๋นํ๋ ์ปฌ๋ผ์ ๋ต๋ณ ์ฌ๋ถ(ANSWER_AT)์ "Y"๋ก ๋ฃ์ด์ฃผ๊ณ , ๋ต๋ณ ๋ด์ฉ(InqryCn), ๋ต๊ธ ์์ฑ์ ์ผ๋ จ๋ฒํธ(answerUserSn)๋ฅผ ์ ๋ ฅ ํด ์ฃผ๊ณ , ์์ฑ์ผ์ SQL now()๋ฅผ ์ด์ฉํด์ ๋ฃ์ด์ฃผ๋ ๊ฒ์ด์์.
๐ฝ ๊ฒฐ๊ณผ ํ๋ฉด