Service & ServiceImpl
- 지금까지는
XML-Dao 연결
, Service만 만들고 바로 거기에 함수 정의 후 Controller 갖다 씀
과 같은 형식으로 작성했다.
- 하지만 이제는 Service 역시 interface로 만든 후 ServiceImpl이 그것을 implements 한 후 자세한 내용을 작성하겠다.
- 어노테이션
@Service
는 Service에서 ServiceImpl로 옮겨가지만, Controller
는 여전히 인터페이스인 Service를 @Autowired
로 가져와 사용한다.
- 스프링 프레임워크에서 Service와 ServiceImpl은 주로 비즈니스 로직을 처리하는 데 사용됩니다.
- Service 인터페이스는 비즈니스 로직의 추상화된 메소드를 정의하는 역할을 합니다. 이 인터페이스는 DAO(Data Access Object)와 같은 데이터 액세스 계층과 통합됩니다.
- ServiceImpl 클래스는 Service 인터페이스를 구현하며, 비즈니스 로직을 실제로 수행하는 구현체입니다. 이 클래스는 Service 인터페이스의 추상 메소드를 구체적으로 구현하고, DAO를 사용하여 데이터를 액세스합니다. 이렇게 Service 인터페이스와 ServiceImpl 클래스를 분리하는 이유는 다음과 같습니다.
- 유연성: Service 인터페이스와 ServiceImpl 클래스를 분리하면, 비즈니스 로직을 쉽게 변경할 수 있습니다. Service 인터페이스를 수정하면, 그 인터페이스를 구현하는 모든 ServiceImpl 클래스가 영향을 받습니다. 따라서 인터페이스를 변경하면, 비즈니스 로직을 변경할 수 있습니다.
- 테스트 용이성: Service 인터페이스와 ServiceImpl 클래스를 분리하면, 단위 테스트를 쉽게 작성할 수 있습니다. 비즈니스 로직을 처리하는 ServiceImpl 클래스를 모킹(mocking)하여 Service 인터페이스의 메소드를 테스트할 수 있습니다.
- 코드 가독성: Service 인터페이스와 ServiceImpl 클래스를 분리하면, 코드의 가독성을 높일 수 있습니다. 비즈니스 로직을 처리하는 ServiceImpl 클래스는 복잡한 로직을 포함할 수 있으며, 이를 Service 인터페이스에서 분리함으로써 코드를 보다 쉽게 이해할 수 있습니다.
UPDATE를 사용해서 DELETE 기능 대체
화면
SQL
SELECT
ROWNUM as num,
a.no,
a.subject,
a.name,
a.password,
a.regdate,
a.contents,
a.available,
a.regroup,
a.relevel,
a.restep,
a.hit
FROM
(SELECT no,
CASE
WHEN available = 0 THEN '삭제된 글입니다.'
WHEN available = 1 THEN subject
END AS subject, name, password, regdate,
contents, available, regroup, relevel, restep, hit FROM REPLYBOARD
order by regroup desc, relevel asc) a
마이바티스
<select id="getAllReplyBoard" resultType="ReplyBoardDto">
SELECT
ROWNUM as num,
a.no,
a.subject,
a.name,
a.password,
a.regdate,
a.contents,
a.available,
a.regroup,
a.relevel,
a.restep,
a.hit
FROM
(SELECT no,
CASE
WHEN available = 0 THEN '삭제된 글입니다.'
WHEN available = 1 THEN subject
END AS subject, name, password, regdate,
contents, available, regroup, relevel, restep, hit FROM REPLYBOARD
order by regroup desc, relevel asc) a
</select>
- 삭제하는 대신 마이바티스에서 select함수를 구현할 때 available (1, 0) 기준으로 1이면 subject 그대로 출력되게, 0이면 "삭제된 글입니다."가 출력되게 한다 : CASE WHEN 사용
HTML - ThymeLeaf
- 타임리프 + a href + 삼항연산자 이용하여 삭제된 글이면 클릭 방지
a th:href="${item.available == 1 ? '/board/view?no=' + item.no : 'javascript:void(0)'
<tbody>
<tr th:each="item : ${boardList}">
<td scope="row">[[${item.no}]]<span th:value="${item.available}"></span></td>
<td class="space1" th:class="'space'+${item.reStep}">
<a th:href="${item.available == 1 ? '/board/view?no=' + item.no : 'javascript:void(0)'}"
th:styleappend="${item.available == 0 ? 'color: #b384f5;' : ''}"
th:text="${item.subject}" href="view.html"
class="cursorSubject"> 제목이 들어갑니다. </a>
</td>
<td th:text="${item.name}">글쓴 사람 이름</td>
<td th:text="${item.regDate}">2023.03.23</td>
<td th:text="${item.hit}">1 </td>
</tr>
</tbody>
SCSS
- 답글 부분은 앞에
ㄴ
붙어야 하니까
- SCSS까지 타임리프랑 연동시켜서 저렇게 하드코딩 안 하고 반복문 돌려버리고 싶은데 그 방법을 잘 모르겠어서 나중에 한번 시도해 볼 예정
.space1 {
padding-left: 0px !important;
}
.space2 {
&:before {
content: "└";
}
padding-left: 30px !important;
}
.space3 {
&:before {
content: "└";
}
padding-left: 60px !important;
}
참고