예전에 입대하기 직전에 장고로 만들었던
todo 리스트?, 개발일지 작성,관리 앱? 개발 일정 관리 캘린더앱?
뭔지 모르겠는데 아무튼 그 프로젝트를 Spring으로 다시 만들어보기로 했다.
만들다 보니 재밌었던 부분, 새롭게 배운점, 고민점들이 많이 생겨서 여기에 적어보기로 했다.
사실 만들면서 정리해야 했던 글인데 귀찮아서 미루고 미루다가 대충 마무리 하고 적게 됐다.
이 글을 읽는 분들이 알고 있는 점이나 비슷한 경험, 좋은 아이디어가 있다면 댓글 달아주면 많은 도움이 될 것 같다.
1. 주요 기능 설계
- 유저 회원가입, 로그인 기능
- 유저들끼리 모여서 스터디를 구상할 수 있는 워크스페이스 기능
- 워크스페이스 내에서 일정을 추가하고 참여할 수 있는 기능
- 일정 내에서 본인의 코멘트(개발일지)를 작성할 수 있는 기능
2. 엔티티 설계

보다시피 유저와 워크스페이스, 유저와 스케줄은 N:M의 관계이다.
그리고 사진엔 안나와있지만 워크스페이스:스케줄은 1:N 관계이며
유저,스케줄과 개발일지 역시 1:N의 관계이다.
1) pk값으로 뭘 사용하는 것이 좋을까?
pk값을 뭘로 할지 고민을 많이 해봤다.
필드마다 unique 한 특성을 많이 가지는 컬럼이 많다.
User은 로그인시 사용하는 id인 accountId
Workspace는 이름인 name 등등..
결론은 name, accountId등은 나중에 바뀔 가능성이 존재하므로
pk는 그냥 increment PK인 id를 만든 후 사용하기로 했다.
나중에 DB를 변경하거나 분산할 일이 존재하면 UUID로 하는 방법도 있겠지만,
이번 프로젝트에선 그럴 일이 절대 없으므로 그냥 increment PK를 쓰기로 했다.
2) 비밀번호를 DB에 그대로 저장해도 될까?
당연히 안된다.
이번 프로젝트는 토이 프로젝트라 귀찮아서 그냥 varchar을 사용하고 넘어갔는데,
좀 더 규모가 커지거나 실제로 배포할 프로젝트라면 당연히 문제가 될 것이다.
정확히는 DB가 유출될 경우 피해가 될 수 있는 개인정보(이름, 이메일, 비밀번호)등은 암호화해서 저장해야한다.
이 부분은 나중에 공부를 더 한 후 추가해봐야겠다.
3. api 명세 설계 - N vs M 관계에서 rest api를 설계하는 방법


1) 프론트 없이 api 설계하기?
예전에 만들었던 api 명세를 조금 수정하려 했는데, 생각해보니까 이 프로젝트 프론트랑 제대로 된 피그마가 없다.
그냥 api만 만들면 되니까, 상상속의 프론트와 피그마로 api를 만들려고 했는데 정말 잘못된 생각이었다.
사용자 화면에 맞춰서 api를 설계하는 것이 기본인데, 사용자 화면이 명확하게 정의되어 있지 않으니까
api 명세도 계속해서 바뀌고, 일관성도 없어졌다. 이번 프로젝트에서 내가 한 가장 큰 실수였던 것 같다...
2) N vs M (워크스페이스/유저, 스케줄/유저) 관계에서의 url 설계
특정 워크스페이스에 속한 유저를 모두 찾아야 할 때?
/workspaces/1/users
/users?workspaceId=1
반대로 특정 유저가 참여하는 워크스페이스를 모두 찾을 때?
/users/2/workspaces
/workspaces?userId=2
어떤 구조가 더 좋을까? 에 대해 많이 고민해봤다.
결론은 상황에 맞춰서 쓰자인 것 같다.
프론트에서 구현할 화면에 어떤 정보가 중심인지, 다른 부가 정보는 뭐가 필요한지를 잘 고려해서 선택해야 할 것 같다.
둘 다 구현해 놓는 방법도 있고,
workspaces에서 검색 조건이 다양하고 자주 쓰인다 싶으면 후자를
그렇지 않다면 전자를 사용할 것 같다.
혹은 /woskspace/1 같은 url에서 유저 정보를 포함한 상세 정보를 모두 보내는 방법도 있다.
물론 그러면 유저 정보 외에 다른 불필요한 정보가 보내지는 단점도 있는데, 이는 restAPI의 어쩔 수 없는 단점인 것 같다.
이부분은 graphQL을 좀 더 공부해봐야 될 것 같다.
3) url에 pk값을 그대로 사용해도 될까?
보통 pk값 필드로 auto increment 를 사용할텐데
이러면 사용자가 url에 pk값 앞 뒤로 다른 값을 넣어서 다른 사용자의 데의터를 조회할 수 있다.
그렇다고 api url에 pk 값 대신 다른 값을 넣기엔 마땅한 unique 값이 없어 새로운 필드를 정의해야하고 복잡해진다.
uuid를 pk에 사용하기엔 128bit 라는 uuid 용량 문제와 url이 복잡해진다는 문제가 있다.
결론은 그냥 pk값을 그대로 쓰면서 인증 인가를 사용해서 정보 접근에 제한을 두려고 한다.
4. 구현과정에서 발생한 고민점들
1) Dto 매핑전략
https://www.inflearn.com/questions/30618/%EA%B6%81%EA%B8%88%ED%95%A9%EB%8B%88%EB%8B%A4
궁금합니다. - 인프런 | 질문 & 답변
안녕하세요 진짜 좋은 강의와 선생님의 답변으로 많이 배우고 있습니다. 강의를 따라 하다보니 몇가지 궁금증이 생겼습니다.1. controller에서 responseEntity 를 안쓰시던데 딱히 이유가 있을까요?2.계
www.inflearn.com
API 를 제작하다 보면 Entity를 직접 반환하면 안되므로 필연적으로 Dto를 사용하게 된다.
View 단계에서 사용하는 Dto를 Controller, Service 중 어느 곳에서 변환하는 것이 좋을까 고민을 많이 해봤다.
i) Controller에서 변환하기
장점 : service가 dto에 의존하지 않게 된다. (의존관계 단순화)
dto는 화면 구현에 의존해 api 설계가 변경될 시 쉽게 바뀔 수 있음
dto 세부사항 수정시 service의 코드가 바뀌지 않아도 됨
단점 : Entity 생성시 의존관계가 있는 Entity 생성을 controller에서 맡아서 하게 되는데
핵심 비즈니스 로직 이라고 할 수 있는 중복 조회, 연관관계 매핑 등을 Controller 단에서 하게 됨.
이는 Controller가 여러 Service 객체들에 의존하게 만듦.
OSIV 문제도 발생. dto 매핑을 트랜잭션 종려 후 진행하면 Lazy Loding을 처리할 경우 오류가 발생함.
ii) Service에서 변환하기
장점 : service가 핵심 비즈니스 로직 (중복 조회, 연관관계 매핑) 등을 모두 담당하고 controller의 코드가 깔끔해짐.
dto 변환을 Service 함수 트랜잭션 내에서 처리하므로 osiv 문제 해결.
단점 : service 객체가 화면(dto)에 의존하게 됨.
dto 변경 시 service 코드도 변경해야함.
결론은 섞어서 사용하기로 했다.
이게 뭔가 싶겠지만 dto 변환을 controller에서 하기 힘든 가장 힘든 상황이 Entity 생성 시 로직 때문이었다.
그렇다고 조회 등의 모든 상황에서 dto가 service로 보내진다면 service 코드가 의존하는 dto가 너무 많아진다.
그러나 생성 시에는 결국 dto가 변경되면 controller, service 혹은 mapper를 사용하면 mapper객체든
연관관계가 있는 다른 객체를 같이 바꾸는 수 밖에 없는 것 같았다.
그래서 생성 로직만 service 객체까지 dto를 보내고, 나머지 다른 로직에선 controller에서 변환해서 service에 보내기로 했다.
그리고 나중에 프로젝트 규모가 커지면
그때 osiv를 false로 바꾸고 조회 생성 모두 dto에 의존하는 api 전용 service를 새로 만들고 분리시키는 것이 좋을 것 같다.
2) Dto 파일들 관리 방법

영한 센세의 답변이다.
i) 도메인 패키지 안에 포함하기
ii) 별도의 dto 패키지를 만들기 (여러 패키지에서 공유될 시)
iii) 사용되는 repository나 service 계층에 두기
나는 여러 패키지에서 공유하지 않는데도 2번을 사용했다.
이게 구조가 제일 깔끔하고 사용하기 편한 것 같다.
대신 dto에서 Entity를 제외한 다른 패키지를 절대 의존하지 않도록 했다.
3)Swagger를 꼭 써야할까?
그냥 postman 쓰면 안되는 걸까?
라는 생각을 하고 있었는데 프론트로 일하고 있는 친구가 제발 써달라고 했다.
프론트에서 요청과정에서 실수 방지, 결과 테스트가 훨씬 편하다고 했었던 것 같다.
springdoc을 이용해서 swagger를 구현하기로 했다.
https://colabear754.tistory.com/99
[Spring Boot] Springdoc 라이브러리를 통한 Swagger 적용
목차 기본 환경 IntelliJ Ultimate 2022.3 Spring Boot 2.7.7 Kotlin 1.7.21(JDK 11) Springdoc Openapi UI 1.6.11 Springdoc은 무엇인가? 이전에 Spring Boot 프로젝트에 Swagger UI를 적용하는 포스트를 작성한 적이 있다. 해당 포
colabear754.tistory.com
'Spring > Spring 기본' 카테고리의 다른 글
사지방에서 Spring boot 공부하기 #6 - Autowired와 자동 의존관계 주입 (0) | 2023.05.08 |
---|---|
사지방에서 Spring boot 공부하기 #5 - 스프링 빈 등록과 조회 (0) | 2023.04.22 |
사지방에서 Spring boot 공부하기 #4 - 스프링 빈이란? (0) | 2023.04.18 |
사지방에서 Spring boot 공부하기 #3 - IOC와 DI (0) | 2023.04.16 |
사지방에서 Spring boot 공부하기 #2 - 스프링과 객체지향 (2) | 2023.04.16 |