single-page 회원관리 폼 만들기

2019-08-19
  • single page : CRUD(가입+수정+삭제+리스트 보여주기)를 Single page 처리
  • REST API 이용

개발순서 (MVC 2 패턴으로 함)

DAO설정
Controller
Service
View

참고사항

  1. REST API 연습용입니다.
    기존에 사용하던 코드를 재활용하였으므로, 변수명의 차이가 있을 수 있습니다.
  2. 회원정보 수정에서의 parametertype 문제
    Map으로 설정해야 하나,
    빠르게 제작하기 위하여 model(DTO)인 EditMember를 parameter로 설정함.
  3. 회원가입시 not null 조건인 ID, PW, NAME만 기입하도록 하였습니다.






결과화면

회원가입화면

결과화면1

회원수정화면

결과화면2




DAO 설정

//인터페이스 작성
public interface MemberDao {
	
	public Member selectById(String id) ; //회원한명의 정보가져오기(login + update )
	public int deleteMember(int idx) ; //삭제
	
	/* Rest Api를 위한 메서드 */
	public List<Member> selectAllList();
	public int insertMem(Member member); 
	public int updateMem(Member member); //업데이트 수정
}
<!-- mapper.xml 작성 -->
<mapper namespace="com.ny.mm.dao.MemberDao">
    <!-- SQL의 컬럼명과 객체의 변수명(field)이 다르므로 resultMap을 통해 호환가능하도록 만듬 -->
    <resultMap type="com.ny.mm.model.member.Member" id="MemberVO">
        <result property="idx" column="idx_m"/>
        <result property="id" column="id"/>
        <result property="pw" column="pw"/>
        <result property="name" column="name"/>
        <result property="photo" column="photo"/>
        <result property="regDate" column="regdate"/>
        <result property="phone" column="phone"/>
    </resultMap>

    <!-- 회원한명의정보가져오기 -->
    <select id="selectById" resultMap="MemberVO" >
        select * from moonchild.member 
        where id = #{id}
    </select>
    <!-- 회원삭제 -->
    <delete id="deleteMember">
        delete from moonchild.member 
        where idx_m = #{idx}
    </delete>
    <!-- 회원리스트가져오기 -->
    <select id="selectAllList" resultMap="MemberVO">
        select * from moonchild.member 
        order by regdate desc 
    </select>
    <!-- 회원가입 -->
    <insert id="insertMem" parameterType="com.ny.mm.model.member.Member">
        insert into moonchild.member (ID, PW, NAME) values (#{id}, #{pw}, #{name})
    </insert>
    <!-- 회원정보수정 -->
    <update id="updateMem" parameterType="com.ny.mm.model.member.EditMember">
        update moonchild.member 
        set name = #{name},
        pw = #{pw} 
        where idx_m = #{idx}
    </update>
</mapper>






Controller 설정

  1. pw는 JsonIgnore로 설정되어 있음.
  2. /rest-api/members 공통 URI 설정
  3. CRUD 설명
    • /rest-api/members method: GET
      리스트 보여주기
    • /rest-api/members method: POST
      회원가입
    • /rest-api/members/{id} method: GET
      해당 아이디의 회원정보 보여주기(수정을 위함)
    • /rest-api/members method: PUT
      회원정보 수정
    • /rest-api/members/{idx} method: DELETE
      회원 삭제(탈퇴)






회원수정(service, controller, DTO 등)

설명 회원수정이 가장 까다로웠으므로, REST API Controller 중 회원수정과 관련된 것(service와 controller, model 등)만 올립니다.






service

	@Autowired
	private SqlSessionTemplate template;
	private MemberDao dao;
	
	//수정할 멤버 가져오기
	public Member select(String id) {
		dao = template.getMapper(MemberDao.class);
		Member member = dao.selectById(id);
		
		return member;
	}
	//해당멤버의 정보 변경
	public int editRest(EditMember edit) {
		dao = template.getMapper(MemberDao.class);
		int result = 0;
		
		Member member = edit.toMemberRest();
		result = dao.updateMem(member);
		return result;
	}






controller

@Controller
@RequestMapping("/rest-api/members")
public class RestApiController {
		
	@Autowired
	private memEditService editService;
    
	//수정:회원정보가져오기
	@CrossOrigin
	@ResponseBody
	@RequestMapping(value = "/{id}", method = RequestMethod.GET)
	public Member geteditMember(@PathVariable("id") String id) {
		return editService.select(id);
	}
	
	//회원수정
	@CrossOrigin
	@ResponseBody
	@RequestMapping(method = RequestMethod.PUT)
	public int editMember(@RequestBody EditMember edit) {
		return editService.editRest(edit);
	}
}
  • @Contoroller
    RestApiController 를 controller로 인식하도록 어노테이션 설정.
  • @CrossOrigin
    client와 server를 분리할 때 발생할 수 있는 크로스도메인 이슈를 해결하기 위한 설정. 해당 이슈는 서버측에서 해결하는 게 보편적이라 함. client가 요청하는 위치가 달라도 해당 메서드를 사용할 수 있도록 한다.
  • RequestParam 과 PathVariable

    RequestParam 은 naver.com/search?page=12 와 같이 URL 자체에 전달된 parameter를 호출
    PathVariable 은 naver.com/search/index/1 REST API에서 값을 호출할 때 사용

    • RequestMapping의 value = “{ 템플릿변수 }“의 템플릿 변수와
    • @PathVariable 어노테이션에서 불러오는 템플릿 변수는 동일한 이름(변수명)을 갖는다.
    • 해당 템플릿변수를 불러와 변수로 사용가능!






view

//수정버튼 클릭시 실행(수정할 멤버의 정보 가져오기)
function edit(id) {
    if(confirm('정말 수정할거야?????리얼리????')){
        $.ajax({
            url:'http://localhost:8080/mc/rest-api/members/'+id,
            type: 'GET',
            error: function() {
                alert('error.....');
                list();
            },
            success: function(data) {
                //alert(data.idx);

                $('#join').css('display','none');  //가입폼 안보이게 하고
                $('#edit').css('display','block'); //수정폼 보이게

                var output = '';
                output += '아이디는안바꿔줘'
                output += '<input type="text" value="'+data.id +'" disabled><br>\n';
                output += '패스워드는?????? ';
                output += '<input type="password" id="pw2" name="pw"> <br>\n';
                output += '이름 좀 알려줄래?';
                output += '<input type="text" id="name2" name="name"> <br>\n';
                output += '<span class="submit" onclick="getEdit('+data.idx+')">';
                output += '수정할래요오오오옹!</span>';
                $('#editForm').html(output);
            }
        });
    }
}
//수정할래요오오오옹! 이라는 버튼을 클릭 할 때 (== 수정 update 전송 버튼)
function getEdit(idx) {

    $.ajax({
        url:'http://localhost:8080/mc/rest-api/members',
        type: 'PUT',
        data: JSON.stringify({
            idx: idx,
            pw : $('#pw2').val(),
            name : $('#name2').val()
        }),
        contentType: 'application/json;charset=utf-8',
        dataType: 'json',
        success: function(data) {

            if(data > 0 ){
                alert('수정되었습니다');
            } else {
                alert('실-패');
            }
        },
        error: function(){
            alert('error ㅠㅠㅠㅠ');
        },
        complete: function() {
            list();
            $('#edit').css('display','none');
            $('#join').css('display','block');
        }
    });
}






TIL

  • complete 를 쓰면 성공/에러에 상관없이 실행함.
    가독성이 좋아짐!
    순서는 success - complete 혹은 error - complete 순.
  • edit 에서는 controller에서 Member 타입으로 받아오기 때문에 data.id 와 같이 get메서드를 호출 할 수 있다.
  • getEdit 은 result값을 int 타입으로 받도록 만들어 success 에서 바로 체크하도록 함.






추가: EditMember

public class EditMember {
	/**
    * 참고로 REST-API에서만 사용하는 변수/메서드만 편집하여 올림
    * getter setter 설정하였음.
    */
    
	private int idx;
	private String id;
	private String pw;
	private String name;

	public Member toMemberRest() {
		Member member = new Member();
		member.setIdx(idx);
		member.setPw(pw);
		member.setName(name);
		
		return member;
	}
}