- deleteRecruit()

위치 : /web/recruitment/RecruitmentController.class

@DeleteMapping("/delete")
    public ApiResponse<String> deleteRecruit(@RequestBody DeleteRecruitRequest request) {
        String response = recruitmentService.deleteRecruit(request);
        return ApiResponse.success(response);
}

- deleteRecruit()

위치 : /service/recruitment/RecruitmentService.class

public String deleteRecruit(DeleteRecruitRequest request) {
        Optional<Recruitment> findRecruit = recruitmentRepository.findById(request.getId());
        String position = findRecruit.get().getPosition();

        recruitmentRepository.delete(findRecruit.get());

        return "해당 " + position + " 채용 공고가 삭제되었습니다.";
}

 

- DeleteRecruitRequest

위치 : /web/recruitment/dto/request

@Getter
public class DeleteRecruitRequest {
    private Long id;
}

 

Postman 

Delete http://localhost:8080/recruitment/delete

Request Body

{   
    "id" : 1
}

 

Response Body

{
    "data": "해당 Backend Junior Position 채용 공고가 삭제되었습니다."
}

- updateRecruit()

위치 : /web/recruitment/RecruitmentController.class

@PatchMapping("/update")
public ApiResponse<UpdateRecruitResponse> updateRecruit(@RequestBody UpdateRecruitRequest request) {
    UpdateRecruitResponse response = recruitmentService.updateRecruit(request);
    return ApiResponse.success(response);
}

 

- updateRecruit()

위치 : /service/RecruitmentService.class

user validation 이나 exception을 하지 않아서 그런지 코드가 약간 빈약해보인다 

public UpdateRecruitResponse updateRecruit(UpdateRecruitRequest request) {

    Optional<Recruitment> findRecruit = recruitmentRepository.findById(request.getId());

    findRecruit.get().setPosition(request.getPosition());
    findRecruit.get().setReward(request.getReward());
    findRecruit.get().setContents(request.getContents());
    findRecruit.get().setTechInfo(request.getTechInfo());

    Recruitment updated = recruitmentRepository.save(findRecruit.get());

    UpdateRecruitResponse response = UpdateRecruitResponse.of(updated);

    return response;
}

 

- UpdateRecruitRequest

위치 : /web/recruitment/dto/request

@ToString
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UpdateRecruitRequest {

    private Long id;
    private String position;
    private Integer reward;
    private String contents;
    private String techInfo;
}

 

- UpdateRecruitResponse

위치 : /web/recruitment/dto/response

@ToString
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class UpdateRecruitResponse {

    private String position;
    private Integer reward;
    private String contents;
    private String techInfo;

    @Builder
    public UpdateRecruitResponse(String position, Integer reward, String contents, String techInfo) {
        this.position = position;
        this.reward = reward;
        this.contents = contents;
        this.techInfo = techInfo;
    }

    public static UpdateRecruitResponse of(Recruitment recruitment) {
        UpdateRecruitResponse response = UpdateRecruitResponse.builder()
                .position(recruitment.getPosition())
                .reward(recruitment.getReward())
                .contents(recruitment.getContents())
                .techInfo(recruitment.getTechInfo())
                .build();
        return response;
    }
}

 

- Postman 

 

PATCH http://localhost:8080/recruitment/update

 

Request Body

  • application/json
{   
    "id" : 1,
    "position" : "Backend Junior Position",
    "reward" : 1300000, //1500000에서 수정
    "contents" : "wanted now hiring backend junior position",
    "techInfo" : "Python" 
}

 

Response Body

{
    "data": {
        "position": "Backend Junior Position",
        "reward": 1300000,
        "contents": "wanted now hiring backend junior position",
        "techInfo": "Python"
    }
}

- Recruitment Entity 

코드 중복을 피하기 위해 @Builder와 of()를 사용했다 

@Table
@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Recruitment {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long company_id;

    @Setter
    private String position;

    @Setter
    private Integer reward;

    @Setter
    private String contents;

    @Setter
    private String techInfo;

    @Builder
    public Recruitment(String position, Integer reward, String contents, String techInfo) {
        this.position = position;
        this.reward = reward;
        this.contents = contents;
        this.techInfo = techInfo;
    }

    public static Recruitment of(String position, Integer reward, String contents, String techInfo) {
        Recruitment recruitment = Recruitment.builder()
                .position(position)
                .reward(reward)
                .contents(contents)
                .techInfo(techInfo)
                .build();
        return recruitment;
    }
}

 

2. 등록 API 작성

 

- RecruitmentRepository

위치 : /domain/recruitment 

public interface RecruitmentRepository extends JpaRepository<Recruitment, Long> {
}

 

- saveRecruit()

위치 : /service/recruitment/RecruimentService

public SaveRecruitResponse saveRecruit(SaveRecruitRequest request) {
        Recruitment recruitment = Recruitment.builder()
                .position(request.getPosition())
                .reward(request.getReward())
                .contents(request.getContents())
                .techInfo(request.getTechInfo())
                .build();

        Recruitment created = recruitmentRepository.save(recruitment);

        SaveRecruitResponse response = SaveRecruitResponse.of(created);

        return response;
}

 

- saveRecruit

위치 : /web/recruitment/RecruitmentController

@PostMapping("/save")
    public ApiResponse<SaveRecruitResponse> saveRecruit(@RequestBody SaveRecruitRequest request) {
        SaveRecruitResponse response = recruitmentService.saveRecruit(request);
        return ApiResponse.success(response);
}

 

- SaveRecruitRequest

위치 : /web/recruitment/request

@Getter
public class SaveRecruitRequest {

    private String position;
    private Integer reward;
    private String contents;
    private String techInfo;

}

 

- SaveRecruitResponse

위치 : /web/recruitment/response

@ToString
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class SaveRecruitResponse {

    private Long id;
    private String position;
    private Integer reward;
    private String contents;
    private String techInfo;

    @Builder
    public SaveRecruitResponse(Long id, String position, Integer reward, String contents, String techInfo) {
        this.id = id;
        this.position = position;
        this.reward = reward;
        this.contents = contents;
        this.techInfo = techInfo;
    }

    public static SaveRecruitResponse of(Recruitment recruitment) {
        SaveRecruitResponse response = SaveRecruitResponse.builder()
                .id(recruitment.getCompany_id())
                .position(recruitment.getPosition())
                .reward(recruitment.getReward())
                .contents(recruitment.getContents())
                .techInfo(recruitment.getTechInfo())
                .build();
        return response;
    }
}

 

 

- Postman 테스트 

 

Request Body

Post http://localhost:8080/recruitment/save

  • application/json
{   
    "position" : "Backend Junior Position",
    "reward" : 1500000,
    "contents" : "wanted now hiring backend junior position",
    "techInfo" : "Python" 
}

 

Response Body

{
    "data": {
        "id": 1,
        "position": "Backend Junior Position",
        "reward": 1500000,
        "contents": "wanted now hiring backend junior position",
        "techInfo": "Python"
    }
}

 

인스타그램 광고에서 원티드에서 진행하는 백엔드 프리온보딩이 있길래 지원하려고 했다. 

지원서에 과제 수행한 깃허브를 공유해야했는데, 해당 과제는 Python/Django 또는 JS/Node.js로 진행해야 했다

현재 자바와 스프링 프레임워크만 다룰줄 알아서 지원을 못하는 건가 싶었는데 '지원을 못하더라도 해당 과제를 해보자'라고 생각하게 되었다. 이전 프로젝트에서 공부한 것 복습 겸, 일단 만들어 놓으면 나를 어필할 때 좋을 것 같았다 

그래서 오늘은 깃허브에 레포 생성하고 로컬이랑 연결한 다음, 등록/수정/삭제 API를 구현했다 

이 과정을 기록하면 좋을 것 같아 글을 써본다 

2022.08.23에 시작했고, 3시간 걸렸던 작업이었다 

 

전반적인 코드를 보면 다음을 참고하면 된다. wanted_pre_onboarding

 

1. Git & GitHub로 프로젝트 시작하기 

 

-GitHub에 wanted_pre_onboarding으로 repository 생성하기 

 

- Git이랑 Local 이랑 연결하기(?)

  • 프로젝트 파일 위치로 이동하기 
 desktop/project/project_code/wanted_pre_onboarding
  • 시작 (remote add origin 순서가 맞는지 모르겠다)
git init
git branch -m master main
git add .
git commit -m "first commit"
git remote add origin [Github Repo 주소]
git push -u origin main
  • 완료
Enumerating objects: 24, done.
Counting objects: 100% (24/24), done.
Delta compression using up to 12 threads
Compressing objects: 100% (16/16), done.
Writing objects: 100% (24/24), 60.26 KiB | 15.07 MiB/s, done.
Total 24 (delta 0), reused 0 (delta 0), pack-reused 0
To https://github.com/heyazoo1007/wanted_pre_onboarding.git
 * [new branch]      main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

 

2. 프로젝트 세팅하기 

- MySQL 연동하기 

start.spring.io에서 MySQL 의존성을 다운받은 후, application.properties에서 다음과 같이 설정하면 된다 

이후 MySQLWorkbench에서 해당 db를 생성해야하는데, 자세한 건 다음 포스트를 참고하면 된다 

https://heyazoo1007.tistory.com/509

spring.profiles.include=real-db
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57InnoDBDialect
spring.session.store-type=jdbc

# Mysql
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/onboarding?serverTimezone=Asia/Seoul&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=password

# JPA
spring.jpa.hibernate.ddl-auto=create
spring.jpa.generate-ddl-auto=true
spring.jpa.show_sql = true

# Logging
logging.level.org.springframework.web=DEBUG

 

- /common/ApiResponse.Class 작성하기 

통일된 응답을 해야하는데, 코드를 일일이 적는 것보다 클래스로 처리하는게 더 효율적이다 

data의 타입이 General Type이라 어떤 타입이 와도 수용가능하다 

이전 프로젝트에서는 statusCode와 statusMessage를 같이 넣었고, errorCode도 구현했는데 

이번엔 간단하게 구현했다. 필요하면 위의 것들 추가할 생각이다 

@ToString
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class ApiResponse<T> {

    public static final ApiResponse<String> SUCCESS = success(null);

    private T data;

    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(data);
    }
}

'개인프로젝트 > 과제' 카테고리의 다른 글

5-2. 채용공고 검색 API (가산점 요소)  (0) 2022.08.25
5-1. 채용공고 목록 API  (0) 2022.08.24
4. 삭제 API  (0) 2022.08.23
3. 수정 API  (0) 2022.08.23
2. 등록 API 생성  (0) 2022.08.23

+ Recent posts