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가 요청하는 위치가 달라도 해당 메서드를 사용할 수 있도록 한다.
  • RequestParamPathVariable

    RequestParamnaver.com/search?page=12 와 같이 URL 자체에 전달된 parameter를 호출
    PathVariablenaver.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;
	}
}