Search

#014 #ajax 사용하기

현 상황

기업 사용자가 작성한 공고에 지원한 지원자들을 확인 할 수 있는 기능이 필요하다.

onclick 함수 설정

[ 호출 ]

버튼 내부에 onclick=(” ”) 함수를 설정한다. ajax 비동기 통신을 할 것이므로 버튼 action 매핑이 아닌 onclick으로 함수를 호출 함수에 머스태치로 값을 넘겨 함수 파라메터에 넣어주면 해당 변수로 값이 전달 된다.
// 해당 jobsId는 findApplicant함수의 파라메터로 값이 전달된다. <button type="button" onclick="findApplicant({{jobsId}})" class="btn btn-mint offer-table-btn">지원자 보기</button>
Java
복사

[ 테스트 ]

화면에 해당 함수를 호출하는 버튼을 준비하고 개발자 도구를 켜서 콘솔에 값이 날라오는지 확인해야 된다.

ajax로직 구현

[ function findApplicant ( )]

// api주소를 호출하여 매핑된 메소드를 실행하며 해당 값을 전달한다. function findApplicant(jobsId){ $.ajax({ url: "/api/find-applicants", type: "post", data: { jobsId: jobsId } }).done(( )=>{ }).fail(( )=>{ }); }
Java
복사

ApiController

[ controller ]

@PostMapping을 사용해서 ajax로 호출하는 주소를 명시해준다. 바디데이터로 넘어오기 때문에 @RequestParam으로 파라메터 값을 받는다. ——> 반드시 괄호안의 변수명이 ajax에서 넘어오는 name값이랑 이름이 같아야 한다!
테스트

DTO 만들기

[ 화면에 필요한 필드값 찾기 ]

내가 필요한 정보를 적어본다.

근데 로직을 잘 생각해야된다….

공고번호로 지원된 이력서들을 조회해야되므로 지원된 이력서란 apply 상태 값이 1이 아닌 것들을 조회해야한다. 그러므로 apply로 조회해서 이력서를 찾는게 좋겠다고 판단
// 공고번호로 지원내역을 찾는데, Apply의 상태값이 1이 아니여야 한다. @Query("select a from Apply a where a.isPass not in ('1') and a.jobs.id = :jobsId") List<Apply> findAllByJidAn1(@Param("jobsId") Integer jobsId);
Java
복사

화면에 뿌려질 RusaDTO ( Resume, User, SkillList, Apply )

public class CompResponse { @Data // Resume랑 User랑 SkillList랑 Apply를 담을 DTO public static class RusaDTO { private Integer id; // user private String myName; // resume private Integer resumeId; private String title; private String career; private List<SkillDTO> skillList; // apply private Boolean isPass; private Boolean isApply; public RusaDTO(Integer id, User user, Resume resume, Apply apply) { this.id = id; this.myName = user.getMyName(); this.resumeId = resume.getId(); this.title = resume.getTitle(); this.career = resume.getCareer(); this.skillList = resume.getSkillList().stream() .map(SkillDTO::new) .collect(Collectors.toList()); // 1. 지원x 2.지원중 3.합격 4.불합격 if (apply.getIsPass().equals("1")) { this.isApply = false; } else if (apply.getIsPass().equals("2")) { this.isApply = true; } else if (apply.getIsPass().equals("3")) { this.isApply = true; this.isPass = true; } else if (apply.getIsPass().equals("4")) { this.isApply = true; this.isPass = false; } } }
Java
복사
화면에 필요한 정보를 담을 DTO, DTO 만드는 설명은 또 길어질 거 같아서 다른 블로그에 따로 작성을 하겠다. 이제 서비스 레이어가 필요하다

CompService

[ ApiController에 의존성 주입]

[ findApplicants () ]

@RequiredArgsConstructor @Service public class CompService { private final ApplyJPARepository applyJPARepo; public List<CompResponse.RusaDTO> findApplicants(Integer jobsId) { //공고에 지원한 이력서를 전부 찾는데, 그 중 지원안한 상태는 제외해서 조회 List<Apply> applyList = applyJPARepo.findAllByJidAn1(jobsId); // DTO를 받을 그릇 준비 List<CompResponse.RusaDTO> rusaDTOList = new ArrayList<>(); /* * 원래 for문으로 조회해서 주입하였으나 그 방식은 서버에 부담이 크다. * 쿼리를 for문으로 날린다는게... */ applyList.stream().map(apply -> { // apply에 Resume가 매핑되어있어서 가져옴 Resume resume = apply.getResume(); /* * 근데 apply안에 resume안에 user는 잘 가져올수있을까?? * 그래서 sout찍어보기 테스트 */ User user = apply.getResume().getUser(); System.out.println(resume.getUser().toString()); return rusaDTOList.add(CompResponse.RusaDTO.builder() .user(user).resume(resume).apply(apply).build()); }).collect(Collectors.toList()); for (int i = 0; i < rusaDTOList.size(); i++) { rusaDTOList.get(i).setId(i+1); } return rusaDTOList; }
Java
복사
이 메소드를 만들고 apply 객체 안에 있는 resume 객체 안에 있는 user를 가져 올 수 있을까? 라는 궁금증이 생겨서 테스트해보기로 함

Junit테스트

결과값은 1번공고에 1번 사용자와 3번 사용자가 지원을 했으므로, 1,3이 뜨면 된다.
@Import(CompService.class) @DataJpaTest public class CompServiceTest { @Autowired private CompService compService; @Test public void findApplicants_test(){ // given int jobsId = 1; // when compService.findApplicants(jobsId); // then //결과값은 1번공고에 1번 사용자와 3번 사용자가 지원을 했으므로, //1,3이 뜨면 된다. }
Java
복사

[ apiController가 완성이 되었다.]

@RequiredArgsConstructor @RestController public class CompApiController { private final CompService compService; @PostMapping("/api/find-applicants") public List<CompResponse.RusaDTO> findApplicants (@RequestParam("jobsId") Integer jId){ return compService.findApplicants(jId); } }
Java
복사
이제 이 값이 ajax로직의 done () 섹션으로 가게 되는 것이다. 타입이 List로 날아간다는 거 다시 한 번기억하자.

다시 ajax로 복귀

값이 잘 넘어오는지 테스트 먼저 실행

근데 id를 세팅해주는거 깜빡했다. 조회결과 id번호 매기기

다시 ajax로 돌아와서 done()이 실행 로직

done이 실행이 되면 커스터마이징된 html을 List갯수대로 넣어줘야 되는 로직이다.

Render () 커스터마이징 html

대체할 부분을 선택한다.

보통 기존에 반복문 로직의 시작 행과 끝행을 선택하면 된다.

render 함수에 위 반복문을 잘라내서 붙여넣는다.

함수 내부에 temp 변수를 선언한다. → let temp = ` ` (백틱사용) 백틱 내부가 html의 문법에 적용되는 구간이다.

주입되는 usraDTO로 아래 문법으로 필드 값을 가져온다.

기존에 있던 필드를 모두 ${변수.필드값} 으로 대체해야된다. 그럼 반복되는 값에 맞게 동적으로 변할 것이다.

만약에 html 내부에 for문 구현이 필요하다면?!?!

반복 되지 않는 부분은 백틱 내부에 넣고 변수지정을 해준다. 여기선 temp 사용 여러항목을 반복해야되는 요소는 백틱 외부에서 구현한다. 여기선 자바로직으로 사용 a += 1 과 같은 동일한 문법으로 temp += ‘블럭’으로 temp변수에 추가 html로 업데이트 해준 것과 같다.

정리

onclick함수 설정 → ajax URL 매핑 → api컨트롤러 → DTO만들기 ajax.done로직 구현 → render 함수 설정 → 커스터마이징 html

이렇게 지원자 보기를 누르면 해당 공고에 지원한 이력서들을 비동기 통신으로 뿌리게 되었다.